Composer

A controlled, auto-growing text field with an integrated footer and send action. The application owns the draft, submission, errors, and queueing policy.

37%
Enter sends · Shift+Enter adds a line · IME composition never submits
const [draft, setDraft] = useState("");

<Composer
  aria-label="Message"
  value={draft}
  onValueChange={setDraft}
  onSubmit={() => send(draft)}
  footer={
    <Button size="small" bare color="secondary" onClick={openSettings}>
      Settings
    </Button>
  }
/>;
PropPurpose
value, onValueChangeControlled draft; never cleared implicitly
onSubmitCalled by Send or unmodified Enter; ignored for IME composition
footerCompact controls below the text
actionOptional replacement for the default send button
submitDisabledDisable submission while leaving the draft editable
submitLabelAccessible send label; defaults to “Send message”
embeddedTransparent surface for inline review or another container; retains focus feedback
jssRoot, jssSurface and textarea customization

Also accepts textarea attributes. Shift+Enter inserts a newline. Empty/whitespace drafts cannot submit. The field uses a 1px neutral surface outline; footer controls receive their own keyboard indicators. Invalid input retains a red outline.

The default type is 14px/20px; growth is bounded at 180px. These defaults need no app-specific CSS. TextArea uses native field-sizing; use current browsers.