# Prompt Composers

> Four composers for AI products — an image prompt with references, a capsule that grows as you type, a playground with model and temperature controls and a metered box that prices each send.

- Collection: AI Agents
- Tier: pro
- Docs: https://geturui.com/docs/chat-composers
- Install: `npx shadcn@latest add @geturui-pro/chat-composers`
- Dependencies: motion, lucide-react

## Variants

### Image prompt

Large image-prompt composer with drawn reference thumbnails, style chips, an aspect selector with a sliding thumb and an image counter.

Install: `npx shadcn@latest add @geturui-pro/chat-composers-image-prompt`

```tsx
import { ImagePromptComposer } from "@/components/ai/chat-composers/image-prompt";

export function ImagePrompt() {
  const [busy, setBusy] = React.useState(false);
  return (
    <ImagePromptComposer
      generating={busy}
      onGenerate={(req) => {
        setBusy(true);
        generateImages(req).finally(() => setBusy(false));
      }}
      onStop={() => setBusy(false)}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| onGenerate | `(request: ImagePromptRequest) => void` | — | Called with { prompt, styles, aspect, count, references }. |
| generating | `boolean` | false | Turns Generate into Stop. |
| onStop | `() => void` | — | Called by the Stop button. |
| styles / defaultStyles | `string[]` | — | Chip options and the ones on at start. |
| maxStyles | `number` | 3 | Most chips on at once; the oldest turns off. |
| aspects / defaultAspect | `AspectRatio[] / AspectRatio` | "4:5" | Ratios offered and the initial one. |
| counts / defaultCount | `number[] / number` | [1, 2, 4] / 2 | Image counts offered. |
| defaultReferences | `ImagePromptReference[]` | — | Initial reference chips ({ id, name, tone? }). |
| defaultValue / placeholder | `string` | — | Initial prompt and placeholder. |

### Capsule

Fully rounded single-line capsule that springs taller and softens its corners as text wraps; voice swaps to send once you type.

Install: `npx shadcn@latest add @geturui-pro/chat-composers-capsule`

```tsx
import { CapsuleComposer } from "@/components/ai/chat-composers/capsule";

export function Composer() {
  return <CapsuleComposer placeholder="Message Atlas" onSubmit={(text) => send(text)} onVoice={startDictation} />;
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| onSubmit | `(value: string) => void` | — | Enter sends; Shift+Enter adds a line. |
| onAttach | `() => void` | — | Shows the plus button. |
| onVoice | `() => void` | — | Shows a voice button while the field is empty. |
| maxRows | `number` | 6 | Lines before the field scrolls. |
| placeholder | `string` | "Message GetUrUI" | Field placeholder. |
| disabled | `boolean` | — | Disables the composer. |

### Playground

Playground composer with a toolbar: model menu, temperature popover with presets and a slider, max-token switch and tool toggles.

Install: `npx shadcn@latest add @geturui-pro/chat-composers-playground`

```tsx
import { PlaygroundComposer } from "@/components/ai/chat-composers/playground";

export function Playground() {
  const [running, setRunning] = React.useState(false);
  return (
    <PlaygroundComposer
      running={running}
      onRun={(prompt, settings) => {
        setRunning(true);
        runPrompt(prompt, settings).finally(() => setRunning(false));
      }}
      onStop={() => setRunning(false)}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| onRun | `(prompt: string, settings: PlaygroundSettings) => void` | — | Run button or Cmd/Ctrl+Enter. |
| running | `boolean` | false | Turns Run into Stop. |
| onStop | `() => void` | — | Called by Stop. |
| models | `PlaygroundModel[]` | — | Model menu options ({ id, label, description? }). |
| defaultSettings | `Partial<PlaygroundSettings>` | — | Initial { model, temperature, maxTokens, tools }. |
| onSettingsChange | `(settings: PlaygroundSettings) => void` | — | Called on every settings change. |

### Metered

Composer with a credit meter that previews the draft's cost as you type and ticks the balance down with a flying debit chip on send.

Install: `npx shadcn@latest add @geturui-pro/chat-composers-metered`

```tsx
import { MeteredComposer } from "@/components/ai/chat-composers/metered";

export function MeteredChat() {
  const [credits, setCredits] = React.useState(1240);
  return (
    <MeteredComposer
      credits={credits}
      maxCredits={2000}
      onCreditsChange={setCredits}
      onSubmit={(text, cost) => send(text, cost)}
      onTopUp={() => openBilling()}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| credits / defaultCredits | `number` | 1240 | Controlled or initial balance. |
| maxCredits | `number` | 2000 | Plan size; the meter's scale. |
| estimateCost | `(text: string) => number` | — | Cost of a draft. Default: 4 + 1 per 60 characters. |
| onSubmit | `(value: string, cost: number) => void` | — | Called after a send. |
| onCreditsChange | `(credits: number) => void` | — | Called with the new balance. |
| onTopUp | `() => void` | — | Shows Top up when the balance runs low. |
| lowThreshold | `number` | 0.15 | Fraction of the plan that turns the meter ember. |
| resetLabel | `string` | "Resets Oct 1" | Small print beside the meter. |

## Accessibility

- Every textarea is labelled; IME composition is respected before Enter or Cmd/Ctrl+Enter submits.
- Chips and toggles use aria-pressed; aspect ratio, image count and token limits are radio groups; popovers close on Escape and return focus.
- Icon buttons carry labels that describe the current action (send, stop, voice, remove).

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
