Select
Chooses one value from a known collection and exposes a button-triggered, keyboard-navigable popup.
Contract
| Axis | Behavior |
|---|---|
| value | uncontrolled with defaultValue, controlled with value and onValueChange |
| open | uncontrolled with defaultOpen, controlled with open and onOpenChange |
| disclosure | Trigger owns focus; Portal, Positioner, and Popup own the floating layer |
| popup geometry | popup width is at least the trigger width and normally 256 px, capped at 320 px and the available viewport; option padding fills each highlighted row |
| collection | groups, labels, separators, disabled items, text, and indicators describe the menu anatomy |
| forms | name, form, required, and inputRef integrate with native submission, validation, and reset |
Use TRSelect.Trigger uiSize="md" when the trigger belongs to a dense control surface.
Install
pnpm add @tinyrack/uiScroll inside the code area to read long lines.
Styles
@import '@tinyrack/ui/components/select.css';Scroll inside the code area to read long lines.
Imports
import { TRSelect } from '@tinyrack/ui/components/select';
import { TRForm } from '@tinyrack/ui/components/form';
import { TRField } from '@tinyrack/ui/components/field';
import { TRButton } from '@tinyrack/ui/components/button';
import { ChevronDown } from 'lucide-react';Scroll inside the code area to read long lines.
Playground
Usage
Examples
Trigger sizes permalink
Choose the trigger density independently from the popup collection.
Long scrolling collection permalink
Open the popup to verify constrained height, scroll arrows, long labels, and highlighted focus treatment.
API
The complete anatomy is Root, Label, Trigger, Value, Icon, Portal, Backdrop, Positioner, Popup, List, Item, ItemIndicator, ItemText, Arrow, ScrollDownArrow, ScrollUpArrow, Group, GroupLabel, and Separator. Every part is available as both TRSelect.Part and a named TRSelectPart export, with matching TRSelectPartProps and TRSelectPartState types.
| Purpose | Public props and defaults |
|---|---|
| value | defaultValue or controlled value; multiple={false} by default; items maps values to displayed labels |
| disclosure | defaultOpen={false} or controlled open; modal={true} and highlightItemOnHover={true} by default |
| availability | disabled={false}, readOnly={false}, and required={false} |
| trigger | `uiSize="md" |
| positioning | Positioner opens 4 px below the trigger and does not accept placement props; it flips above when the available space requires it |
| forms | name, form, autoComplete, and inputRef; uncontrolled selects restore defaultValue on native reset |
Give Trigger an accessible name. Keyboard users can open with Arrow Down, move through enabled options, use typeahead, confirm with Enter, and dismiss with Escape while focus returns to the trigger. Pointer hover, open, highlighted, and selected states use background emphasis only; the focus border appears only for keyboard-origin focus. Keep value and open controlled independently when needed. Use disabled for unavailable controls and readOnly for focusable values that cannot change.