Prompt input

프롬프트 입력창

A chat text box that grows with the number of lines typed, with attach and send controls.

Also known as: ComposerChat input box
···
html
<div class="composer">
  <button class="icon" aria-label="첨부"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 11.5V7a4 4 0 0 0-4-4h-2a4 4 0 0 0-4 4v10a3 3 0 0 0 6 0V8"/></svg></button>
  <textarea id="ta" rows="1" readonly placeholder="메시지를 입력하세요"></textarea>
  <button class="send" id="send" aria-label="전송"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M5 12h14M13 6l6 6-6 6"/></svg></button>
</div>
css
.composer{width:min(300px,94%);display:flex;align-items:flex-end;gap:6px;padding:8px;border-radius:16px;background:var(--surface);border:1px solid var(--line)}
.icon{flex-shrink:0;width:28px;height:28px;border:0;border-radius:8px;background:none;color:var(--muted);display:grid;place-items:center;cursor:pointer}
textarea{flex:1;resize:none;border:0;background:none;color:var(--fg);font:inherit;font-size:12.5px;line-height:1.5;max-height:76px;overflow-y:auto;padding:5px 0}
textarea::placeholder{color:var(--muted)}
.send{flex-shrink:0;width:28px;height:28px;border-radius:50%;border:0;background:var(--line);color:var(--muted);display:grid;place-items:center;cursor:pointer;transition:background .18s,color .18s}
.send[data-ready]{background:var(--accent);color:#fff}
js
const ta = document.getElementById('ta'), send = document.getElementById('send');
const line = '내일까지 발표자료 3장 요약해서\n핵심만 불릿으로 정리해줘';
let i = 0;
function type() {
  ta.value = line.slice(0, i);
  ta.style.height = 'auto';
  ta.style.height = Math.min(ta.scrollHeight, 76) + 'px';
  if (i < line.length) { i++; setTimeout(type, 42); }
  else { send.setAttribute('data-ready', ''); setTimeout(sendMsg, 900); }
}
function sendMsg() {
  send.removeAttribute('data-ready');
  ta.value = '';
  ta.style.height = 'auto';
  setTimeout(() => { i = 0; type(); }, 1000);
}
setTimeout(type, 400);

Built on a multi-line <textarea>, not a single-line <input>. The core trick is autosize: on every input, reset height to auto, then set it to scrollHeight, so the box grows with content instead of scrolling internally — until it hits a max height, at which point it switches to internal scroll.

The send button stays disabled while the input is empty and fills with color once there's text, previewing whether sending is even possible right now. Enter to send and Shift+Enter for a newline is the convention, though some mobile users expect the opposite — match the platform.

The attach icon often doubles as file/image upload, and a mic icon switches to voice input. More buttons means a narrower text area, so it's worth tucking rarely-used actions behind a + menu instead of lining them all up.

When to use

The default input component for almost any conversational AI product. If input is reliably a single short command, autosize may be more machinery than you need.