Model Selector
The picker for which model answers. A searchable list grouped by provider, where each row carries what decides the choice: what the model is for, what it can do and how much context it holds.
Installation#
Usage#
import {
ModelSelector,
ModelSelectorTrigger,
ModelSelectorContent,
ModelSelectorInput,
ModelSelectorList,
ModelSelectorGroup,
ModelSelectorItem,
ModelSelectorLogo,
ModelSelectorName,
ModelSelectorCapabilities,
ModelSelectorCapability,
ModelSelectorMeta,
} from "@/components/ui/model-selector"
export function Picker() {
const [model, setModel] = React.useState("claude-sonnet-5-5")
return (
<ModelSelector value={model} onValueChange={setModel}>
<ModelSelectorTrigger>Sonnet 5.5</ModelSelectorTrigger>
<ModelSelectorContent>
<ModelSelectorList>
<ModelSelectorGroup heading="Anthropic">
<ModelSelectorItem value="claude-sonnet-5-5">
<ModelSelectorName>Claude Sonnet 5.5</ModelSelectorName>
</ModelSelectorItem>
</ModelSelectorGroup>
</ModelSelectorList>
</ModelSelectorContent>
</ModelSelector>
)
}Anatomy#
import {
ModelSelector,
ModelSelectorTrigger,
ModelSelectorContent,
ModelSelectorInput,
ModelSelectorList,
ModelSelectorGroup,
ModelSelectorItem,
ModelSelectorLogo,
ModelSelectorName,
ModelSelectorCapabilities,
ModelSelectorCapability,
ModelSelectorMeta,
} from "@/components/ui/model-selector"
<ModelSelector>
<ModelSelectorTrigger>
<ModelSelectorLogo />
</ModelSelectorTrigger>
<ModelSelectorContent>
<ModelSelectorInput />
<ModelSelectorList>
<ModelSelectorGroup>
<ModelSelectorItem>
<ModelSelectorLogo />
<ModelSelectorName addon={<ModelSelectorCapabilities>
<ModelSelectorCapability />
</ModelSelectorCapabilities>} />
<ModelSelectorMeta />
</ModelSelectorItem>
</ModelSelectorGroup>
</ModelSelectorList>
</ModelSelectorContent>
</ModelSelector>In a composer#
The trigger is a ghost Button at sm, so it sits on PromptInput's toolbar like every other control there. It shows what you give it, usually the provider's mark and the model's short name, rather than mirroring the row: the toolbar wants “Opus 5.5”, the list wants the full name. Its natural neighbour is the Context Meter, which turns over when you switch to a model with a different window.
Without search#
ModelSelectorInput is optional. Leave it out when the list fits on one screen. Focus then lands on the list itself, so the arrow keys still walk the rows and Enter still chooses.
API reference#
ModelSelector
The root: the selection and the panel's open state. Choosing a model closes the panel.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | The selected model's id, controlled. |
| defaultValue | string | - | The initially selected model's id. |
| onValueChange | (value: string) => void | - | Called with the chosen model's id. |
| open | boolean | - | The panel's open state, controlled. |
| defaultOpen | boolean | false | The panel's initial open state. |
| onOpenChange | (open: boolean) => void | - | Called when the panel opens or closes. |
ModelSelectorTrigger
A ghost Button holding what you pass (a logo and the model's short name), with the caret added. No press scale. Forwards Button props.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | ButtonProps["size"] | "sm" | Match the bar it sits on. |
ModelSelectorContent
The panel: a Command inside the Popover, with the Popover as its only surface. Forwards PopoverContent props.
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Models" | The list's accessible name. |
| align | "start" | "center" | "end" | "start" | Alignment to the trigger. |
ModelSelectorInput
The search row. Matches the id and keywords. Forwards CommandInput props.
ModelSelectorList
The scrolling list, with the empty state. Forwards native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| empty | React.ReactNode | "No models found." | Shown when a search matches nothing. |
ModelSelectorGroup
A provider's models under its name; collapses when filtered empty. Forwards CommandGroup props (heading).
ModelSelectorItem
One model. Adds the selected check in a fixed slot. Forwards CommandItem props.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | - | The model's id: what gets selected and searched. |
| keywords | string[] | - | More terms to match: the display name, the provider. |
| disabled | boolean | - | Shown but not choosable (no access on this plan). |
| Data attribute | Description |
|---|---|
| data-selected | Present on the chosen model. |
ModelSelectorLogo
A provider's mark in the row's 20px box, with a hairline over it. aria-hidden.
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | - | An image URL. Or pass your own SVG as children. |
ModelSelectorName
The model's name with an optional second line and something after it.
| Prop | Type | Default | Description |
|---|---|---|---|
| description | React.ReactNode | - | A quiet second line: what the model is for. |
| addon | React.ReactNode | - | After the name: ModelSelectorCapabilities or a Badge. |
ModelSelectorCapabilities
A run of small muted glyphs after the name. Renders a <span>.
ModelSelectorCapability
One capability: a small glyph that explains itself in a Tooltip on hover (a plain hint for the name alone, the rich tooltip with a description). The name is also screen-reader text in the row.
| Prop | Type | Default | Description |
|---|---|---|---|
| label* | string | - | What the glyph means: Vision, Reasoning. |
| description | React.ReactNode | - | One line under the name in the tooltip: what it means for this model. |
ModelSelectorMeta
The trailing read-out (context window, price) in tabular-nums. Renders a <span>.