AI chat

Chat input

The composer: an auto-growing textarea, an attachment slot, and a send button.

Client componentSource

Import

import { ChatInput } from '@the_viveksingh/vivek-ui'

A composer

Enter sends, Shift+Enter adds a line, and the box grows to maxRows before it scrolls. onSubmit receives the trimmed draft and is never called while empty, disabled or busy.

Press Enter to send, Shift+Enter for a new line

<ChatInput
  label="Message"
  hideLabel
  placeholder="Ask anything. Enter sends, Shift+Enter adds a line."
  maxRows={6}
  onSubmit={send}
/>

With attachments

The attachments slot sits above the box and takes any node.

screenshot.pnglogs.txt

Press Enter to send, Shift+Enter for a new line

<ChatInput
  label="Message"
  hideLabel
  attachments={
    <Stack direction="horizontal" gap={2} wrap>
      {files.map((file) => (
        <Badge key={file.name} tone="neutral">{file.name}</Badge>
      ))}
    </Stack>
  }
  onSubmit={send}
/>

While a request is in flight

busy disables sending, so a second Enter cannot fire the same request twice - the same reason Button has loading.

Send is disabled while busy, so a request cannot be fired twice.

<ChatInput busy label="Message" hideLabel hint="Waiting for a reply..." />

Props

Generated from the package's own type declarations, so this table cannot drift from the code.

Props for ChatInput
PropTypeDefaultDescription
valuestringControlled draft text. Pair with `onValueChange`.
defaultValuestringInitial draft text while uncontrolled.
onValueChange(value: string) => voidCalled on every keystroke, and with an empty string when a send clears the box.
onSubmit(value: string) => voidCalled with the trimmed draft on send. Never called while empty, disabled or busy.
placeholderstring
maxRowsnumberRows the box may grow to before it starts scrolling. Defaults to 8.
minRowsnumberRows the box starts at. Defaults to 1.
disabledboolean
busybooleanA reply is in flight: the send button spins and Enter will not submit.
attachmentsReactNodeSlot above the box for attachment chips, file pickers, model pickers.
submitLabelstringSend button text. Defaults to `Send`.
labelstringTextarea label. A real `<label>`, visually hidden unless `hideLabel` is `false`.
hideLabelbooleanKeep the label off screen. Defaults to `true`.
hintReactNodeThe `aria-describedby` hint that makes Enter-to-send discoverable. Pass `null` to drop it entirely (then say it somewhere else - do not simply remove it).
clearOnSubmitbooleanEmpty the box after a successful send. Defaults to `true`.
textareaPropsOmit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue' | 'onChange' | 'onKeyDown' | 'id' | 'disabled' | 'placeholder'>Escape hatch onto the textarea itself.
textareaRefRef<HTMLTextAreaElement>Ref to the textarea. The forwarded ref goes to the `<form>` root.

Rendering