AIComponentBeta

Prompt Input.

Say it, send it, stop it.

The message composer: a textarea that grows with its content, a row for tools such as a model picker, and one button that sends, then stops the reply while it is in progress.

Make it yours

Preparing the example…

PROPERTIES3

Composition

Anatomy

Root owns the value (controlled or not) and the request status. While submitted or streaming, Enter does not send and Submit becomes Stop; typing the next message is still allowed.

Component structure
PromptInput.Root (form; value, onSubmit, status, onStop)
├── PromptInput.Textarea — autosizes; Enter sends
└── PromptInput.Footer
    ├── PromptInput.Tools — Select, Toggle, …
    └── PromptInput.Submit — Send ↔ Stop

A place to start

Usage

Import the stylesheet once at your application root. This complete example reflects the properties selected above.

Loading example…

Details that make a difference

Examples & states

The finer details

API reference

Generated from Dixy’s local TypeScript interfaces. Native HTML attributes and refs are forwarded. The table covers Dixy’s own options.

PromptInputRoot

PropType / descriptionDefault
valuestring

Controlled text. Pair with `onValueChange`.

—
defaultValuestring

Initial text when uncontrolled.

""
onValueChange((value: string) => void)

Called on every edit.

—
onSubmit((text: string) => void)

Called with the trimmed text when the user sends. Uncontrolled inputs clear themselves afterwards. Not called for empty text or while busy.

—
statusChatStatus

Request state. While submitted or streaming, the send button becomes a stop button and Enter does not send.

ready
onStop(() => void)

Called when the user stops a reply in progress.

—
disabledboolean

Disable typing and sending.

false

PromptInputTextarea

PropType / descriptionDefault
aria-labelstring

Accessible name.

Message
maxHeightnumber

Tallest the field grows before it scrolls, in pixels.

200

PromptInputSubmit

PropType / descriptionDefault
sendLabelstring

Accessible name while ready.

Send message
stopLabelstring

Accessible name while a reply is in progress.

Stop generating
childrenReactNode | ((stopping: boolean) => ReactNode)

Replace the icons. Receives whether the button currently stops.

—

Built from the same foundations

Styling tokens

Change Theme settings above to compare appearance, accent, neutral, radius, spacing density, motion and direction. Override component aliases on a Theme root so custom properties follow portaled content too. The wrapper merges className, style, refs and render composition with its owning primitive.

TokenPurpose
--dixy-radius-cardThe component-specific starting point.
--dixy-font-label-mdControl label font and line height; body roles remain readable in text inputs.
--dixy-color-background-selectedSelected surfaces use semantic color across appearances.
--dixy-color-border-focusFocus indication remains visible independently of shadows.
--dixy-spacing-inset-smDensity-aware component padding.
--dixy-motion-transition-feedbackShort state feedback, reduced by the inherited motion setting.
Explore theme customization

Consider everyone

Accessibility

Send and Stop are one button that changes its name, so focus survives the switch. With empty input the button is aria-disabled but still focusable, so focus is never dropped to the page after sending. The textarea has an accessible name, not just a placeholder.

EnterSend the message.
Shift + EnterAdd a new line.
Enter during IME compositionConfirm the composed text; never sends.
TabMove to the tools, then to Send or Stop.

Target: WCAG 2.2 AA. Automated tests cover selected behavior; manual screen-reader, contrast, and zoom validation remain part of the release checklist.

THE THINKING BEHIND IT

Build it. Then understand it.

isComposing is the difference between a Japanese user confirming a word and sending half a sentence. Safari ends composition before keydown, so keyCode 229 is checked as well.

A token to follow--dixy-radius-card

Nothing up our sleeves

Source
UP NEXTSuggestions