Skip to content
Kura UI

Model Picker

beta

Searchable popover for choosing an AI model, grouped by provider, with capability icons, context size, speed and cost hints.

@kura-ui/react/model-pickerCopy page for agents.mdregistry.json

Three models

minimal

Searchable, grouped, controlled

Eight models across providers, a disabled tier, badges, capability icons and a controlled open state.

full

Using claude-sonnet-5-5

In a composer toolbar

Opens upward from the composer's toolbar.

composition

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/model-picker.json

Copies the source into components/kura/model-picker with its dependencies (kura-theme, popover, use-controllable-state, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • Let the user switch the model in a chat composer toolbar or a chat header.
  • Compare models at a glance: vision/tools/reasoning support, context window, speed and price tier.
  • Any “choose one of N models/agents/providers” selector that benefits from search and grouping.

Reach for something else when

  • Running actions or navigating — use command-palette.
  • Inserting commands while typing a prompt — use slash-command-menu.
  • Two or three static options without metadata — a segmented control or plain select is enough.

Props

PropTypeDefaultDescription
models*readonly ModelPickerModel[]—Models: { id, name, provider?, description?, capabilities?, contextWindow?, speed?: 1|2|3, cost?: 1|2|3, badge?, disabled?, icon? }. Grouped by provider in first-seen order.
valuestring—Controlled selected model id.
defaultValuestring—Initial id when uncontrolled. Defaults to the first enabled model.
onValueChange(id: string, model: ModelPickerModel) => void—Called when the user picks a model.
openboolean—Controlled open state.
defaultOpenbooleanfalseInitial open state.
onOpenChange(open: boolean) => void—Open state changes.
searchableboolean—Show the search field. Default: true when there are more than 6 models.
placeholderstring"Select model"Trigger text when nothing is selected.
searchPlaceholderstring"Search models…"Search field placeholder.
emptyMessagestring"No models match"Shown when the search has no results.
showDetailsbooleantrueFixed-height footer describing the highlighted model (no layout shift).
side"top" | "bottom""bottom"Preferred popover side; flips on collision. Use top in a bottom-docked composer.
align"start" | "center" | "end""start"Popover alignment relative to the trigger.
size"sm" | "md""sm"Trigger height: sm 32px for toolbars, md 36px.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. ModelPickerThe trigger button (provider mark, model name, chevron). data-state = open | closed.data-slot="model-picker"
  2. ModelPickerContentPopover surface; scales from the trigger (origin-aware).data-slot="model-picker-content"
  3. ModelPickerSearchSearch row; the input is the combobox that owns keyboard navigation.data-slot="model-picker-search"
  4. ModelPickerGrouprole=group per provider, labelled by its heading.data-slot="model-picker-group"
  5. ModelPickerItemrole=option row: name, badge, meta line, capability icons, check. data-active, data-disabled.data-slot="model-picker-item"
  6. ModelPickerDetailsFooter with the highlighted model's description.data-slot="model-picker-details"

Accessibility

  • Role: combobox + listbox
  • The trigger is labelled “Model: <name>”. On open, focus moves to the search combobox (or the listbox when not searchable) and returns to the trigger on close.
  • Highlighting uses aria-activedescendant, so focus never leaves the search field while navigating.
  • Options expose aria-selected and aria-disabled; provider groups are role=group with their heading as label.
  • Capability icons, speed and cost meters carry visually hidden text (“Vision”, “Fast”, “High cost”), so the meta line reads naturally.
  • Reduced motion: The popover fades without scale or travel and the chevron flips without rotating; highlight changes are instant in all modes.
KeysAction
Enter / Space / ArrowDownOpen from the trigger
ArrowDown / ArrowUpMove the highlight (wraps, skips disabled models)
Home / EndFirst / last model (when the search is empty)
EnterChoose the highlighted model and close
EscapeClose and return focus to the trigger

Notes for agents

  • Pass `side="top"` inside a composer docked to the bottom of the viewport.
  • speed: 3 = fast, 1 = slow/thorough. cost: 1 = cheap, 3 = expensive. Omit either to hide it.
  • `icon` takes a 16px provider logo; without it a monogram of the provider is shown.
  • formatContextWindow(200000) → "200K" is exported for use elsewhere (e.g. a context-meter).