Composer
A chat message input: a real <textarea> that grows with field-sizing: content (no form — a composer submits on a keystroke or a button, never page navigation), with leading/trailing action slots and a thinking state for when a response is in flight.
Examples
Basic
Just a placeholder — Cmd/Ctrl+Enter submits by default.
Usage
<Composer placeholder="Ask anything…" />With actions
Leading/trailing slots for attachments, a send button, anything else.
Usage
<Composer
placeholder="Ask anything…"
actionsLeading={
<Button variant="ghost" size="sm" aria-label="Attach" iconStart={<PaperclipIcon />} />
}
actionsTrailing={({ submit }) => (
<Button variant="primary" size="sm" onClick={submit}>
Send
</Button>
)}
/>Thinking state
An animated border sweep signals an in-flight response and blocks submission. The submitted query stays visible.
Usage
<Composer
placeholder="Ask anything…"
defaultValue="How do I theme Kernel with a custom accent colour?"
thinking
/>Playground
Toggle every adjustable prop and watch the component — and the code — update live.
submitOn
thinking
disabled
Usage
<Composer placeholder="Ask anything…" /><kernel-composer placeholder="Ask anything…"></kernel-composer>Props
| Prop | Type | Default |
|---|---|---|
value / defaultValue | string | — |
onValueChange | (value: string) => void | — |
onSubmit | (value: string) => void | — |
submitOn | "mod+enter" | "enter" | "mod+enter" |
placeholder | string | — |
disabled | boolean | false |
thinking | boolean | false |
actionsLeading / actionsTrailing | ReactNode | (ctx: { submit: () => void }) => ReactNode | — |
Accessibility
- The textarea gets an
aria-labelfromplaceholderwhen no visible label is present. - Growth is pure CSS (
field-sizing: content), so there's no layout thrash or focus loss as content grows. - The thinking-state border sweep is decorative (
aria-hiddenviapointer-events: noneand no text content) and freezes underprefers-reduced-motion, replaced by a static tinted border — the state is still visible, just not animated.