VexellDocs · v1.5

AI primitive

ChatComposer

The textarea-based prompt input every modern AI product needs. Ships with model picker, reasoning toggle, character counter, optimistic submit state, and a stop-mid-stream button. Wire your model SDK at onSubmit.

Usage

Pick your edition with the tabs. Selection syncs across this page and the rest of the docs.

tsx
import { ChatComposer } from '@/components/organisms'

export default function Page() {
  return (
    <ChatComposer
      layout="standard"
      models={[
        { id: 'sonnet', label: 'Claude Sonnet 4.6', hint: 'Most capable' },
        { id: 'haiku',  label: 'Claude Haiku 4.5',  hint: 'Fastest'      },
      ]}
      defaultModel="sonnet"
      reasoningToggle
      onSubmit={async ({ prompt, model, reasoning }) => {
        // Wire your model SDK here. Server action, fetch, anything.
        // The composer handles its own optimistic state.
      }}
    />
  )
}

Props

Same surface in both editions; the HTML version exposes equivalents through Alpinex-data.

PropTypeDefaultDescription
layout"standard" | "compact""standard"Visual density. Compact reduces padding for sidebar mounts.
modelsArray<{id, label, hint?}>[]Models the user can switch between. Empty array hides the picker.
defaultModelstringfirst model idInitial selection.
reasoningTogglebooleanfalseShow the reasoning-on/off toggle next to the submit button.
maxLengthnumber4000Hard limit on prompt characters. Visible counter at 75% threshold.
onSubmit(payload) => void | Promise<void>Called with { prompt, model, reasoning }. Composer disables itself while a returned promise pends.
onStop() => voidCalled when the user clicks the stop button mid-stream. Optional.

Accessibility

  • role

    Wrapper is a <form>; submit fires on Enter (Shift+Enter inserts newline).

  • keyboard

    Cmd/Ctrl+Enter submits regardless of focus inside the textarea.

  • live

    Submit/disabled state announces via aria-live="polite" on the status row.

  • contrast

    All text meets WCAG AA in both light and dark, including the placeholder.

  • motion

    The pending shimmer respects prefers-reduced-motion (drops to a static dim).

Read next

  • StreamingResponse — pair the composer with a response card that streams tokens.
  • ModelPicker — standalone model picker if you need it outside the composer.