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
valuestring—Controlled draft text. Pair with `onValueChange`.
defaultValuestring—Initial draft text while uncontrolled.
onValueChange(value: string) => void—Called on every keystroke, and with an empty string when a send clears the box.
onSubmit(value: string) => void—Called with the trimmed draft on send. Never called while empty, disabled or busy.
placeholderstring——
maxRowsnumber—Rows the box may grow to before it starts scrolling. Defaults to 8.
minRowsnumber—Rows the box starts at. Defaults to 1.
disabledboolean——
busyboolean—A reply is in flight: the send button spins and Enter will not submit.
attachmentsReactNode—Slot above the box for attachment chips, file pickers, model pickers.
submitLabelstring—Send button text. Defaults to `Send`.
labelstring—Textarea label. A real `<label>`, visually hidden unless `hideLabel` is `false`.
hideLabelboolean—Keep the label off screen. Defaults to `true`.
hintReactNode—The `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).
clearOnSubmitboolean—Empty 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