Prompt Input
A clean AI prompt box that grows open on focus, lit by a Beam border glow, with a ChatGPT-style + menu, model picker, attachments, voice input and run / stop.
Preview
Click the input to open it up.
Setup
Install with the shadcn CLI
One command adds every file, the npm packages and any Kinetik components it builds on. Needs a components.json; the CLI offers to create one if your project has none.
Or install manually
- 1
Run in your terminal:
$npm install clsx tailwind-merge border-beam framer-motion lucide-react - 2
Copy
lib/utils.tsfrom the Code tab. Skip if you already havecn(). - 3
Copy
styles/tokens.cssfrom the Code tab and import it in your global CSS after Tailwind:@import "./styles/tokens.css"; - 4
This component uses Model Selector. Copy
components/ui/model-selector/from the Code tab too, at the same path so the import resolves. Skip any you already have. - 5
Create a
components/ui/prompt-input/folder and copy every file from the Code tab into it. Each file does one job, so you can read or change a piece without the rest. - 6
Import and render:
Exampleimport { PromptInput } from "@/components/ui/prompt-input" <PromptInput onSubmit={(value) => console.log(value)} />
Usage
At rest the input is a small pill. Focusing it springs it open to full width and the toolbar blurs in: an attach menu, a model picker, the mic and the run button. It folds back once focus leaves and nothing is typed or attached.
The + button opens a menu like ChatGPT's: add photos and files or take a photo, then pick a
tool (Create image, Deep research, Web search, Think longer). A picked tool shows as a blue chip
beside +, changes the placeholder, and arrives in onSubmit as tool; click the chip to turn
it off. Pass your own list with tools. The model picker is the Model Selector component, so it keeps
the same badges, colours, sliding highlight and keyboard support. Copy its
components/ui/model-selector/ folder too; both folders are in the Code tab.
The glow around the box is Beam (border-beam on npm) by
Libraries.dev. It switches on when the box opens and
speeds up while a prompt is running. Install it with npm install border-beam, and see its docs to
tune the glow.
import { PromptInput } from "@/components/ui/prompt-input"
export function Chat() {
return (
<PromptInput
onSubmit={async (value, { attachments, model, tool, signal }) => {
await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ value, model, tool }),
signal,
})
}}
/>
)
}
Return a promise from onSubmit and the run button turns into a stop button until it
settles. Pressing stop aborts signal and calls onStop.
Images can be added from the menu, dropped onto the input, or pasted into the text.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
onSubmit | (value, context) => void | Promise | — | Context has attachments, model, tool and an AbortSignal. |
onStop | () => void | — | Runs when the user presses stop. |
placeholder | string | "Ask anything…" | Text shown when empty. |
models | ModelOption[] | 3 samples | Same shape as Model Selector: id, name, description, badge, color. |
tools | PromptTool[] | 4 tools | The + menu's tools: id, label, icon, placeholder. |
defaultModel | string | first model | Id of the model picked at start. |
beam | "colorful" | "mono" | "ocean" | "sunset" | … | "colorful" | Beam colour variant, passed to border-beam. |
theme | "light" | "dark" | follows .dark | Beam theme. By default it follows a .dark class on html. |
collapsedWidth | number | 300 | Width at rest (px). |
expandedWidth | number | 600 | Width when open (px). Never wider than its container. |
speech | boolean | true | Show the mic when the browser supports speech recognition. |
label | string | "Prompt" | Accessible name for the text box. |
Accessibility
- Enter runs, Shift + Enter adds a new line, Escape leaves the input
- Menus open on Enter or Space, move with the arrow keys and close on Escape, returning focus to their button
- Run, stop, mic and remove buttons all have labels; running and listening are announced
- Respects
prefers-reduced-motion: the beam stays off and springs become instant