import { ModelSelectorSample } from "@/components/docs/samples/model-selector";
A select component that lets users switch between AI models. Uses item-aligned positioning so the selected model overlays the trigger for a unified look. Integrates with assistant-ui's ModelContext system to automatically propagate the selected model to your backend.
Getting Started#
Add model-selector#
<InstallCommand shadcn={["model-selector"]} />
Use in your application#
Place the ModelSelector inside your thread component, typically in the composer area:
import { ModelSelector } from "@/components/assistant-ui/model-selector";
const ComposerAction: FC = () => {
return (
<div className="flex items-center gap-1">
<ModelSelector
models={[
{ id: "gpt-4o-mini", name: "GPT-4o Mini", description: "Fast and efficient" },
{ id: "gpt-4o", name: "GPT-4o", description: "Balanced performance" },
{ id: "o3", name: "o3", description: "Most capable" },
]}
defaultValue="gpt-4o-mini"
size="sm"
/>
</div>
);
};
Read the model in your API route#
The selected model's id is sent as config.modelName in the request body:
export async function POST(req: Request) {
const { messages, config } = await req.json();
const result = streamText({
model: openai(config?.modelName ?? "gpt-4o"),
messages: await convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
Variants#
Use the variant prop to change the trigger's visual style.
<ModelSelector variant="outline" /> // Border (default)
<ModelSelector variant="ghost" /> // No background
<ModelSelector variant="muted" /> // Solid background
| Variant | Description |
|---|---|
outline | Border with transparent background (default) |
ghost | No background, subtle hover |
muted | Solid secondary background |
Sizes#
Use the size prop to control the trigger dimensions.
<ModelSelector size="sm" /> // Compact (h-8, text-xs)
<ModelSelector size="default" /> // Standard (h-9)
<ModelSelector size="lg" /> // Large (h-10)
Model Options#
Each model in the models array supports:
const models = [
{
id: "gpt-4o", // Sent to backend as config.modelName
name: "GPT-4o", // Display name in trigger and items
description: "Most capable", // Optional subtitle in items only
icon: <SparklesIcon />, // Optional icon (any ReactNode)
},
];
Runtime Integration#
The default ModelSelector export automatically registers the selected model with assistant-ui's ModelContext system. When a user selects a model:
- The component calls
aui.modelContext().register()withconfig.modelName - The
AssistantChatTransportincludesconfigin the request body - Your API route reads
config.modelNameto determine which model to use
This works out of the box with @assistant-ui/react-ai-sdk.
API Reference#
Composable API#
For custom layouts, use the sub-components directly with ModelSelector.Root:
import {
ModelSelectorRoot,
ModelSelectorTrigger,
ModelSelectorContent,
ModelSelectorItem,
} from "@/components/assistant-ui/model-selector";
<ModelSelectorRoot models={models} value={modelId} onValueChange={setModelId}>
<ModelSelectorTrigger variant="outline" />
<ModelSelectorContent />
</ModelSelectorRoot>
| Component | Description |
|---|---|
ModelSelector | Default export with runtime integration |
ModelSelector.Root | Presentational root (no runtime, controlled state) |
ModelSelector.Trigger | CVA-styled trigger showing current model |
ModelSelector.Content | Select content with model items |
ModelSelector.Item | Individual model option with icon, name, description |
ModelSelector#
<ParametersTable
type="ModelSelectorProps"
parameters={[
{
name: "models",
type: "ModelOption[]",
required: true,
description: "Array of available models to display.",
},
{
name: "defaultValue",
type: "string",
description: "Initial model ID for uncontrolled usage.",
},
{
name: "value",
type: "string",
description: "Controlled selected model ID.",
},
{
name: "onValueChange",
type: "(value: string) => void",
description: "Callback when selected model changes.",
},
{
name: "variant",
type: '"outline" | "ghost" | "muted"',
default: '"outline"',
description: "Visual style of the trigger button.",
},
{
name: "size",
type: '"sm" | "default" | "lg"',
default: '"default"',
description: "Size of the trigger button.",
},
{
name: "contentClassName",
type: "string",
description: "Additional class name for the dropdown content.",
},
]}
/>
ModelOption#
<ParametersTable
type="ModelOption"
parameters={[
{
name: "id",
type: "string",
required: true,
description: "Unique identifier sent to the backend as modelName.",
},
{
name: "name",
type: "string",
required: true,
description: "Display name shown in trigger and dropdown.",
},
{
name: "description",
type: "string",
description: "Optional subtitle shown below the model name.",
},
{
name: "icon",
type: "React.ReactNode",
description: "Optional icon displayed before the model name.",
},
]}
/>