Components
Picker
A pill that opens a menu of described choices, for switching a model, agent or mode.
bunx shadcn@latest add @nalarx/pickerUsage
The caller owns open. onToggle fires for the trigger, Escape and an outside press. Picking a row does not close the menu on its own: close it in the row's onClick.
<Picker open={open} onToggle={() => setOpen((o) => !o)} icon="sparkle" active={model !== "auto"} label={current.title}>
<PickerLabel>Model</PickerLabel>
{models.map((m) => (
<PickRow key={m.id} active={m.id === model} title={m.title} desc={m.desc}
onClick={() => { setModel(m.id); setOpen(false); }} />
))}
</Picker>Active with a label, a divider and a disabled row; compact (icon only); disabled:
Choose the model that answers
Choose the model that answers
States
- Active or open: neutral
bg-hoverwash and aline-stronghairline; never orange. - Label change: the label slides in again (
nx-label-swap), off under reduced motion. - Compact: icon only;
labelbecomes the accessible name and the tooltip. - Disabled: 55%, cannot open.
- Rows: the active one is washed with a check; descriptions clamp to two lines with the full text on hover; disabled rows are 55% and skipped.
- Placement: right-aligned under the pill, 260px wide by default, flips up and shrinks to stay inside the screen. It sits on
--z-popover, so it opens over dialogs.
Keyboard
| Key | |
|---|---|
Enter, Space, ArrowDown on the pill | Opens and highlights the first row. |
ArrowDown / ArrowUp, Home / End | Moves between rows. |
| Typing | Jumps to the row whose title starts with it. |
Enter / Space | Picks the row. |
Escape | Closes and returns focus to the pill. |
Props
Picker: open, onToggle, icon, active, label, leadingVisual?, menuWidth? (260), compact?, disabled?, describedBy?, descriptionText?, children.
PickRow: active, title, desc, onClick, leading?, disabled?.
Replaces
Web Picker.tsx (Picker, PickRow, MenuLabel → PickerLabel, MenuDivider → PickerDivider; the facade keeps the old names). menuZIndex is gone: the menu always sits above dialogs.