Shortform Text Editor

by godfrzero

HTML

<h1>
  <div class="seamless"><textarea class="seamless" rows="1">Lorem ipsum dolor sit amet.</textarea></div>
</h1>

<h1>
  <div class="seamless seamless--loading">
    <textarea rows="1">Lorem ipsum dolor sit amet.</textarea>
  </div>
</h1>

<h2>
  <div class="seamless">
    <input type="text" value="Lorem ipsum dolor sit amet.">
  </div>
</h2>

<h1>
<div class="seamless"><textarea rows="1">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea></div>
</h1>

<h2>
  <div class="seamless"><textarea rows="1">Lorem ipsum dolor sit amet.</textarea></div>
</h2>

<h2>
  <div class="seamless"><input type="text" value="Lorem ipsum dolor sit amet."></div>
</h2>

<small><i>
  <div class="seamless"><input type="text" value="Lorem ipsum dolor sit amet."></div>
</i></small>

SCSS

/* Reset Styles */
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Component Styles */
.seamless {
  position: relative;

  &.seamless--loading {
    &:before {
      content: ' ';
      position: absolute;
      top: 0;
      width: 100%;
      height: 2px;
      background: black;
    }
  }

  & > input,
  & > textarea {
    all: inherit;
    border: solid 2px transparent;
    padding: 0 0.2em;
    transition: background 0.25s ease;
    border-radius: 3px;
    margin: 0 8px;
    width: 100%;
    
    &:hover:not(:focus) {
      background: rgba(0, 0, 0, 0.05);
    }
    
    &:focus {
      border: solid 2px rgba(0, 0, 0, 0.1);
    }
  }
}

JavaScript

// TODO: Prevent newlines? Easier to do in React than to worry about it here. Match /s and strip.
//
// Edge doesn't support "all" apparently. So we'll have to pick the relevant properties
// and inherit those. But still. https://caniuse.com/#search=all
function resize ($el) {
	$el.style.height = 'auto';
	$el.style.height = $el.scrollHeight + 'px';
}

window.addEventListener('input', function (event) {
  var $el = event.target;
  
  resize($el);
});

document.querySelectorAll('.seamless').forEach(resize);