Model Picker
The composer-footer model dropdown: models grouped by provider, each group carrying a connection dot, each model a name plus a muted description and context-size chip. A recipe over Select — the popup keeps its debossed tray and the chosen model rises as the embossed key.
tsx
import {
ModelPicker,
ModelPickerContent,
ModelPickerItem,
ModelPickerProvider,
ModelPickerTrigger,
} from "@/registry/seam/ui/model-picker"
const MODELS = {
"fable-5": "Fable 5",
"opus-4-8": "Opus 4.8",
"haiku-4-5": "Haiku 4.5",
"llama-groq": "Llama 4 70B",
}
export default function ModelPickerDemo() {
return (
<ModelPicker items={MODELS} defaultValue="fable-5">
<ModelPickerTrigger />
<ModelPickerContent>
<ModelPickerProvider name="Anthropic" connection="connected">
<ModelPickerItem
value="fable-5"
description="Most capable; deep reasoning"
meta="1M ctx"
>
Fable 5
</ModelPickerItem>
<ModelPickerItem
value="opus-4-8"
description="Strong all-rounder"
meta="200k"
>
Opus 4.8
</ModelPickerItem>
<ModelPickerItem
value="haiku-4-5"
description="Fast and inexpensive"
meta="200k"
>
Haiku 4.5
</ModelPickerItem>
</ModelPickerProvider>
<ModelPickerProvider name="Local" connection="connected">
<ModelPickerItem value="llama-groq" description="On the LAN box">
Llama 4 70B
</ModelPickerItem>
</ModelPickerProvider>
</ModelPickerContent>
</ModelPicker>
)
}bunx --bun @seamui/cli@latest add model-pickerNotes
- Pure Select semantics:
value/onValueChangewith string ids; metadata lives in the item markup. Per-thread persistence is your state, not the component's. - Connection dots follow the monochrome rule — connected is filled primary, error is destructive, off is faint — and each announces as text (“connected”, “connection error”).
- Effort/thinking tiers aren't baked in: put a
mode-selectornext to the picker (the composer-footer example shows the composed row).
Press feedback, reduced motion, and haptics follow the global policy — see Motion and Haptics.