import { PromptInput } from "@elabs-ai/components-ai";npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-aiPaste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.
Add the brand-ui PromptInput component (from @elabs-ai/components-ai) to this project. 1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`. 2. Look PromptInput up before writing code: `npx -y @elabs-ai/components-cli docs PromptInput` prints its real props, variants, what it pairs with and what to avoid. 3. If @elabs-ai/components-ai is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-ai` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-ai`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`. 4. Use it here: [the screen or file, and what it should show] 5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop. 6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.
Avoid
- Treating PromptInput as a controlled textarea — it is a form; use onSubmit, not value/onChange plumbing.
- Submitting model calls from the component — emit the message; the app owns transport.
- Passing children to PromptInputSubmit for every status — the Stop affordance goes invisible while generating; pass it for the resting state only.
- Expecting className to land on the visible well — className styles the outer <form>; use surfaceClassName to reach the well.
PromptInput — the raw composer FORM primitive Composer is built on. Compose PromptInputBody / PromptInputTextarea / PromptInputFooter / PromptInputTools / PromptInputSubmit yourself when you need a bespoke shell; reach for <Composer /> for the standard chat input. tone picks the inner well's fill: "surface" (default, muted — the look every existing usage keeps) or "card", letting the well nest inside an already-tinted outer frame — the "double card" that PromptInput could not express before this prop existed. The card well's fill is theme-driven, not universally "white" — raised (lighter than the outer frame) on light themes, recessed (darker) on dark; see the tone prop doc.
Works with
Contains
Examples
Double Card Toned
The "double card" (#254): a tinted `bg-surface-muted` outer frame around a `tone="card"` well. Raised (lighter than the frame) on light themes, recessed (darker) on dark — check both themes here, not just the light default.
Idle
At rest: Send, disabled until there is text or an attachment.
Running Empty
Running, composer empty — the control IS the Stop affordance (unchanged).
Running With Draft
Running, but the user has typed a follow-up — the P0 fix. The control flips back to Send so the draft can always be submitted mid-turn; brand-ui never asserts what `onSubmit` does with it (queue, interleave — the app decides).
Error State
Failed — an X that stays clickable so the user can retry.
Separate Stop Control
The composed "separate" arrangement: a dedicated `PromptInputStop` beside `PromptInputSubmit`. Never a `mode` prop (component-api.md bans behavioural modes) — compose the two controls instead. While `PromptInputStop` is mounted, `PromptInputSubmit` stays Send in every state; the dedicated control owns stopping.
API
PromptInput
| Prop | Type | Description |
|---|---|---|
accept | string | e.g., "image/*" or leave undefined for any |
multiple | boolean | |
globalDrop | boolean | When true, accepts drops anywhere on document. Default false (opt-in). |
syncHiddenInput | boolean | Render a hidden input with given name and keep it in sync for native form posts. Default false. |
maxFiles | number | Minimal constraints |
maxFileSize | number | bytes |
tone | "surface" | "card" | The fill of the inner well (the `InputGroup` `variant`). `"surface"` (default) is the standard muted composer look; `"card"` renders a `bg-card` well for nesting inside an already-tinted outer frame — the "double card" look (#254). e.g. `<div className="rounded-xl bg-surface-muted p-1.5"><PromptInput tone="card">…</PromptInput></div>`. The well fill is NOT universally "white": `--card` reads lighter (raised) than `--surface-muted` on light themes, but darker (recessed) on dark — the same theme-dependent trade-off documented for `bg-surface-muted`-as-a-well in `styling-and-tokens.md`. The well stays a legible, distinct tone against the outer frame in every theme; only the "raised" framing is light-themes-specific. |
onError | (err: { code: "max_files" | "max_file_size" | "accept"; message: string }) => void | |
onSubmitrequired | ( message: PromptInputMessage, event: FormEvent<HTMLFormElement>, ) => void | Promise<void> | |
surfaceClassName | string | Classes for the inner surface (the visible `InputGroup` well), e.g. to shape its corners. `className` styles the outer `<form>`; this styles the well — the only way to reach it from outside (used by `Composer`). |
PromptInputActionAddAttachments
| Prop | Type | Description |
|---|---|---|
label | string |
PromptInputActionAddScreenshot
| Prop | Type | Description |
|---|---|---|
label | string |
PromptInputActionMenu
PromptInputActionMenuContent
PromptInputActionMenuItem
PromptInputActionMenuTrigger
| Prop | Type | Description |
|---|---|---|
tooltip | PromptInputButtonTooltip |
PromptInputBody
PromptInputButton
| Prop | Type | Description |
|---|---|---|
tooltip | PromptInputButtonTooltip |
PromptInputCommand
PromptInputCommandEmpty
PromptInputCommandGroup
PromptInputCommandInput
PromptInputCommandItem
Theming
The tokens each state resolves to. Change the token and every theme follows.
| State | Token |
|---|---|
| submit | status=ready|submitted|streaming|error |