Model Picker
Preview: In composer
Model selector grouped by provider, with context size and capability badges.
Import
import { ModelPicker } from '@marbleui/ui'Props
<ModelPicker>
| Prop | Type | Default | Description |
|---|---|---|---|
| models *required | ModelOption[] | — | |
| onChange *required | (id: string) => void | — | |
| value *required | string | — | |
| aria-label | string | — | Accessible name of the picker (default "Model"). |
| className | string | — | |
| placeholder | string | 'Choose model' | Trigger text when nothing is selected. |
| variant | 'outline' | 'ghost' | 'ghost' | "ghost": borderless trigger for composers. "outline": field-like. |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria Header · React Aria ListBox · React Aria ListBoxItem · React Aria ListBoxSection · React Aria Popover · React Aria Select · React Aria SelectValue. Follow the primitive's docs for the full keyboard map.
Usage notes
Model menu for a chat composer, grouped by provider, with context size and capability badges. Pass it to PromptInput’s tools. For a general dropdown use Select.
const models: ModelOption[] = [
{ id: 'opus', name: 'Claude Opus 5.5', provider: 'Anthropic', description: 'Most capable, for complex work', context: '1M', badges: ['Reasoning'] },
{ id: 'local', name: 'Local 8B', provider: 'On device', description: 'Private, offline', context: '32K' },
]
<PromptInput onSubmit={send} tools={<ModelPicker models={models} value={model} onChange={setModel} />} />
- Controlled only:
valueis the selected model’sid, andonChangereceives the new one. - Groups follow the order in which each
providerfirst appears.disabled: truekeeps a model visible but unselectable. variant="ghost"(default) is the borderless trigger for composers;"outline"looks like a field, for settings pages.aria-labelnames the picker (default “Model”) andplaceholderis the trigger text with nothing selected (default “Choose model”). Typing on the trigger jumps to matching model names.
Example source · show· hide
import { useState } from 'react'
import { PromptInput } from '../prompt-input'
import { ModelPicker, type ModelOption } from './model-picker'
const models: ModelOption[] = [
{ id: 'opus', name: 'Claude Opus 5.5', provider: 'Anthropic', description: 'Most capable, for complex work', context: '1M', badges: ['Reasoning'] },
{ id: 'sonnet', name: 'Claude Sonnet 5.5', provider: 'Anthropic', description: 'Fast and smart for everyday tasks', context: '1M' },
{ id: 'haiku', name: 'Claude Haiku 5.5', provider: 'Anthropic', description: 'Fastest, for high volume', context: '200K' },
{ id: 'local', name: 'Local 8B', provider: 'On device', description: 'Private, offline', context: '32K', badges: ['Offline'] },
{ id: 'legacy', name: 'Legacy model', provider: 'On device', description: 'Retired', disabled: true },
]
function InComposer() {
const [m, setM] = useState('sonnet')
return <PromptInput className="w-[32rem]" onSubmit={() => {}} tools={<ModelPicker models={models} value={m} onChange={setM} />} />
}
function Outline() {
const [m, setM] = useState('opus')
return <ModelPicker models={models} value={m} onChange={setM} variant="outline" />
}
export const styles = { 'In composer': InComposer, Outline }Source: packages/ui/src/model-picker/model-picker.tsx
Catalog
- Category
- ai-agents
- Priority
- Pro
- Primitive
- composed
- React Aria
- Select
- Base UI
- Select