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

Setup

Install with the shadcn CLI

$npx shadcn@latest add https://kinetikui.vercel.app/r/prompt-input.json

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. 1

    Run in your terminal:

    $npm install clsx tailwind-merge border-beam framer-motion lucide-react
  2. 2

    Copy lib/utils.ts from the Code tab. Skip if you already have cn().

  3. 3

    Copy styles/tokens.css from the Code tab and import it in your global CSS after Tailwind: @import "./styles/tokens.css";

  4. 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. 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. 6

    Import and render:

    Example
    import { 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

PropTypeDefaultNotes
onSubmit(value, context) => void | Promise—Context has attachments, model, tool and an AbortSignal.
onStop() => void—Runs when the user presses stop.
placeholderstring"Ask anything…"Text shown when empty.
modelsModelOption[]3 samplesSame shape as Model Selector: id, name, description, badge, color.
toolsPromptTool[]4 toolsThe + menu's tools: id, label, icon, placeholder.
defaultModelstringfirst modelId of the model picked at start.
beam"colorful" | "mono" | "ocean" | "sunset" | …"colorful"Beam colour variant, passed to border-beam.
theme"light" | "dark"follows .darkBeam theme. By default it follows a .dark class on html.
collapsedWidthnumber300Width at rest (px).
expandedWidthnumber600Width when open (px). Never wider than its container.
speechbooleantrueShow the mic when the browser supports speech recognition.
labelstring"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