Axon 911 Frontend DocsAxon 911 Frontend Docs
Axon 911 Frontend Docs
    Loading navigation…
U
User
Switch to light mode
  1. Components
  2. Chat Input
  3. Usage

Chat Input

Usage

ChatInput is the composer for a chat message. It mirrors PromptInput in ui-ai-elements in behavior, API and composition, and takes its surface and radii from the Figma frame: a 12px surface with a default edge, an add control, the placeholder, and a Send control on a 6px radius. Enter sends and Shift+Enter inserts a newline. The typed area grows with its text up to six lines and then scrolls, and focus stays in it after a send. It renders no label; the screen that places it names it.
When to use
  • The message field of a chat, a text-messaging reply, or a transcript note.
  • A prompt box for an assistant, with context chips, attachments and suggestions.
When not to use
  • Long-form text that wants a Return key for paragraphs: use TextArea.
  • A single-line value that submits a form: use Input.
Keys
KeyResult
Enter (any modifier but Shift)Calls onSend, then clears the composer. Never inserts a newline
Shift+EnterInserts a newline
Enter while an input method is composingConfirms the candidate. Nothing is sent
Backspace after an inline chipRemoves the whole chip
Delete before an inline chipRemoves the whole chip
Arrow keys beside an inline chipStep over the whole chip; Shift extends the selection over it
Enter sends nothing when the text is empty or only whitespace, and nothing while a response is generating or when the composer is read-only. It still does not insert a newline. A press on Send during an input method composition is ignored in the same way.
Sending
onSend(message, segments, details) receives the trimmed text and its content in order. An inline chip is @label in message and a { type: "chip", id, label } segment, so its id survives. Context chips are never part of either. The composer clears after onSend returns; call details.cancel() to keep the text for a send that can fail, then clear it yourself when the message is accepted.
Value
The text is controlled with value and onValueChange, or kept by the composer with defaultValue. The value is the text with each inline chip written as @label. A controlled parent stores every value it is given, including the empty one:
A value that differs from the last one the composer reported replaces the typed area with plain text and removes its inline chips. Newlines in the value become line breaks in the typed area, and a trailing newline gives the caret a second line; the value you wrote is the message you get back from a send. A value written while the typed area has focus puts the caret at its end. hasSendableText is the rule Enter uses.
Chips
  • Inline chips sit in the text and come from handleRef.current.insertChip(chip) or from a chosen suggestion. Each is removable.
  • Context chips are the chips prop: a named row above the typed area, the pinned context the message applies to. They survive a send. Give onChipDismiss to make them removable.
An inline chip behaves as one character of the text:
  • Remove control. Each inline chip has a remove control named by its removeLabel. A press, or Enter, Space, Backspace or Delete on the focused control, removes the chip, announces removedAnnouncement, and puts focus and the caret back in the typed area where the chip was, so typing carries on. onChipDismiss(id, details) runs first with the reason ItemPress; details.cancel() keeps the chip and leaves focus on the control.
  • Backspace and Delete. With the caret directly after a chip Backspace removes the whole chip, and with it directly before a chip Delete does. This holds for Control and Alt too. A selection that covers chips removes them with the rest. onChipDismiss runs with the reason InputChange and cannot cancel. Where the engine keeps the deletion in its undo history (Chrome and Safari), undo restores the chip with its control.
  • Caret. The arrow keys step over a whole chip in one press, in the direction the key points under the text direction, so under right-to-left ArrowLeft moves forward. Shift extends the selection over a chip. A caret that lands inside a chip, as a click or Home can place it in some engines, moves to the chip's edge.
  • Value. A chip is @label in the text, in onValueChange and in onSend's message; segments keeps its id. Copy and cut put the selection on the clipboard the same way.
  • Paste and drop. Both insert plain text at the caret. Markup on the clipboard never makes a chip, and a drag that carries files is left to the page.
  • Paint. Every chip, inline or in the context row, takes the accent tint of Badge's Beta type: the accent-tint fill, label and edge, with the remove control's icon, hover and pressed washes and focus ring on the same tint. Under forced colors the chip keeps a system-colored edge.
  • Wrapping text. A chip is one unit in text that wraps: it is one line tall, never splits across lines, and a chip that does not fit at the end of a line moves whole to the next. A label longer than the line is truncated inside the chip. The text before and after it wraps normally, and the arrow keys step over a chip at a line break as anywhere else.
  • Spacing. Chips sit 4px from the text and from each other, set by a margin and not a space character, so a chip is deleted by one Backspace and the sent text has no extra space.
Spacing
The surface has 8px of padding and 8px between the add control, the text and the actions, and between rows. With no add control the text starts 16px in. Text on its own row takes a further 8px inline and 4px block inset. Context chips and inline chips are 4px apart. The suggestions sit 16px under the surface with 8px between them. Stacked insets the typed row, the header and the controls row 16px, with no padding on the text itself.
Status
Pass the status of a chat hook straight through. While it is "submitted" or "streaming", a send is blocked and the trailing control is Stop when you give onStop and stopLabel, or Send in its pending state when you do not. A disabled composer disables Stop and shows Send disabled; a read-only one keeps Stop usable.
Layout
Reflow keeps the controls on one row until the text would wrap, then drops them under it. Stacked is flush for compact surfaces: two rows from the start, a rule between them, no border, radius or shadow. The add control rests on the translucent --color-fill-default wash rather than Neutral Soft's opaque fill, so it composes over the surface. Its hover and pressed washes are unchanged, and a disabled composer keeps Button's disabled fill.
Naming
ChatInput renders no label. Give aria-label or aria-labelledby. placeholder is copy and is not a name. Every icon-only control is named by a prop: sendLabel, addLabel, stopLabel.
Migrating from PromptInput
onSubmit is onSend, the send, stop and add controls take required names, an attach row carries its own label and icon, and a chip carries the copy of its remove control. The full mapping, with the layout that fits each ChatPanel variant, is in Migrating from ui-ai-elements. Dictation is not carried; see the packages/ui/src/components/chat-input/CONTRACT.md.
Previous
Chain Of Thought / Accessibility
Next
Chat Input / API and Development
On this page
When to use
When not to use
Keys
Sending
Value
Chips
Spacing
Status
Layout
Naming
Migrating from PromptInput