Composer Panel

The two-row composer: a radius-24 card with the prompt on top and the controls underneath, the add menu, a permission picker with Auto, Manual, Plan mode and Bypass all, a model picker with a scrollable provider rail and an effort popover on the chosen model, mic and send, plus a status tab with branch, project folder and context meter hanging off the card's top edge. The single-line Composer pill stays as it is; this is the taller layout for agent surfaces.

Mainproject-sea
57%

Installation

Dark mode ready - this component follows BoardUI semantic tokens automatically. Set up theme switching.

Pro access

Composer Panel is a Pro component.

Your BoardUI Pro license unlocks this component and all of its source files. Activate your license once, then install it directly into your project with the CLI.

01

Activate your license

Use the key from your Lemon Squeezy purchase email. You only need to do this once per machine.

npx boardui@latest login YOUR_LICENSE_KEY
02

Install the component

The CLI copies the source and resolves every BoardUI and npm dependency for you.

npx boardui@latest add composer-panel

This component is included in BoardUI Pro

Get BoardUI Pro now and install it right away.

Permissions

The picker paints its surface only on hover, press, or while the menu is open, so at rest it reads as a label next to the plus button. The menu lists the four modes with a one-line description each and a Learn more link button in the header (learnMoreHref or onLearnMore). Auto is the default; set defaultPermission to start elsewhere, or pass permission and onPermissionChange to own it. The trigger, the menu and the option list also ship on their own as PermissionMenu and COMPOSER_PERMISSIONS.

Auto: Agent decides by itself

{/* Auto is the default; start on another mode */}<ComposerPanel defaultPermission="plan" /> {/* Or own the mode yourself */}const [permission, setPermission] = useState<ComposerPermission>("auto");<ComposerPanel permission={permission} onPermissionChange={setPermission} /> {/* The picker on its own; "Learn more" is a Link Button, a link with href or a button with onLearnMore */}<PermissionMenu value={permission} onChange={setPermission} learnMoreHref="/docs/permissions" />

Model picker

A 341px panel: a scrollable rail of provider marks down the left, and the chosen provider's lineup as radio rows on the right under a Models header with the Quick Search hint. MODEL_PROVIDERSships eighteen realistic lineups, the eight marks the design carries plus ten more from LobeHub's icon set, from OpenAI and Anthropic to Google, Mistral, xAI and Amazon. Only the selected row carries the effort chip; pressing it opens the effort popover with the same six-stop Faster to Smarter slider the pill composer uses. Quick Search, or /, turns the header into a field that filters every lineup at once, each match tagged with its provider; a pick lands you on that provider's list. Every list scrolls. Pass providers for your own catalogue.

OpenAI GPT-5.6 Mini at Medium effort

{/* Start on a model and effort stop; MODEL_PROVIDERS ships eighteen realistic lineups */}<ComposerPanel defaultModel="anthropic/fable-5.1" defaultEffort={3} /> {/* Or own both */}const [model, setModel] = useState("openai/gpt-5.6-mini");const [effort, setEffort] = useState(1); // 0 Low … 5 Max, see EFFORT_LEVELS<ComposerPanel model={model} onModelChange={setModel} effort={effort} onEffortChange={setEffort} /> {/* Your own catalogue, and the picker on its own */}<ModelPicker providers={[{ id: "acme", name: "Acme", logo: "/logos/acme.svg", models: [{ id: "acme/acme-1", name: "Acme 1" }] }]} value={model} onChange={setModel}/>

Status tab

The tab is a 34px grey strip inset 28px on each side, rounded at the top only, carrying the branch, the project folder and the 16px context ring. It is the status slot: render ComposerStatusTab with your own values, drop in anything else, or pass null for the bare card.

release/2.0boardui
82%
{/* Branch, project folder and context meter */}<ComposerPanel status={<ComposerStatusTab branch="release/2.0" project="boardui" context={82} />}/> {/* No tab at all */}<ComposerPanel status={null} />

Wiring it up

The prompt is a textarea that grows a line at a time up to ten lines. Enter sends and Shift+Enter breaks the line; onSubmit receives the text and the field clears itself when uncontrolled. disabled greys out send while a turn is in flight, and inputRef reaches the field for focus.

const [draft, setDraft] = useState("");const inputRef = useRef<HTMLTextAreaElement>(null); <ComposerPanel value={draft} onValueChange={setDraft} onSubmit={(message) => send(message)} // Enter sends, Shift+Enter breaks the line disabled={waiting} placeholder="Hi, what do you need today?" inputRef={inputRef}/>

Attachments

The same card carries a strip of 56px file tiles above the prompt, each drawing the upload ring while its file lands. The tiles, the strip and the sequential upload queue have their own page.