Model Selector
A compact model picker for AI apps with glyphs, badges, a sliding highlight and an optional extended-thinking switch.
Preview
Setup
Install with the shadcn CLI
One command adds every file, the npm packages and any Kinetik components it builds on. Needs a components.json; the CLI offers to create one if your project has none.
Or install manually
- 1
Run in your terminal:
$npm install clsx tailwind-merge framer-motion lucide-react - 2
Copy
lib/utils.tsfrom the Code tab. Skip if you already havecn(). - 3
Copy
styles/tokens.cssfrom the Code tab and import it in your global CSS after Tailwind:@import "./styles/tokens.css"; - 4
Create a
components/ui/model-selector/folder and copy every file from the Code tab into it. Each file does one job, so you can read or change a piece without the rest. - 5
Import and render:
Exampleimport { ModelSelector } from "@/components/ui/model-selector" <ModelSelector models={[{ id: "fast", name: "Fast" }, { id: "pro", name: "Pro" }]} />
Usage
The menu scales out of the trigger with a soft blur, a highlight slides between rows as you hover or arrow through them, and the trigger's label blurs over to the new model when you pick one.
import { ModelSelector } from "@/components/ui/model-selector"
const models = [
{ id: "kinetik-2", name: "Kinetik 2", description: "Smartest for everyday work", badge: "New", color: "#7c5cff" },
{ id: "kinetik-fast", name: "Kinetik Fast", description: "Quick answers", color: "#06b6d4" },
]
export function Picker() {
const [model, setModel] = useState("kinetik-2")
const [thinking, setThinking] = useState(false)
return (
<ModelSelector
models={models}
value={model}
onValueChange={setModel}
thinking={thinking}
onThinkingChange={setThinking}
/>
)
}
Use side="top" when it sits inside a prompt box at the bottom of the screen.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
models | ModelOption[] | — | id, name, description, badge, color, icon, disabled. |
value | string | — | Controlled model id. |
defaultValue | string | first model | Starting model when uncontrolled. |
onValueChange | (id) => void | — | Runs when a model is picked. |
thinking | boolean | — | With onThinkingChange, adds an extended-thinking switch. |
onThinkingChange | (on) => void | — | Runs when the switch flips. |
side | "top" | "bottom" | "bottom" | Which side the menu opens on. |
align | "start" | "end" | "start" | Menu edge that lines up with the trigger. |
Accessibility
- The trigger opens a
listbox; the highlighted row is exposed witharia-activedescendant - Arrow keys, Home and End move the highlight, skipping disabled models; Enter or Space picks
- Escape closes and returns focus to the trigger; the thinking switch is a real
switch