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

$npx shadcn@latest add https://kinetikui.vercel.app/r/model-selector.json

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. 1

    Run in your terminal:

    $npm install clsx tailwind-merge framer-motion lucide-react
  2. 2

    Copy lib/utils.ts from the Code tab. Skip if you already have cn().

  3. 3

    Copy styles/tokens.css from the Code tab and import it in your global CSS after Tailwind: @import "./styles/tokens.css";

  4. 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. 5

    Import and render:

    Example
    import { 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

PropTypeDefaultNotes
modelsModelOption[]—id, name, description, badge, color, icon, disabled.
valuestring—Controlled model id.
defaultValuestringfirst modelStarting model when uncontrolled.
onValueChange(id) => void—Runs when a model is picked.
thinkingboolean—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 with aria-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