Select
Radix behaviour, our clothes. The trigger is an Input: same border, same height per density. The content is less elevated and less round than the shadcn default.
surface-muted fill, not an accent tint — colour stays reserved for meaning. The selected indicator is a ✓ in primary.Required props
SelectField shipped placeholder = 'Escolher…' and emptyText = 'Sem opções' as defaults. A primitive carrying Portuguese cannot be used on an English surface, and nobody noticed because the defaults worked locally. placeholder and emptyText are now required props. The rule generalises: a user-readable string literal in ui/src/ is a defect.
<SelectField
label="Category"
placeholder="Choose a category" {/* required */}
emptyText="No categories yet" {/* required */}
density="touch" {/* keeps 44px rows in the feedback app */}
options={categories}
/>States
closedopenitem highlighteditem selecteddisabledemptyAll six come from Radix — we only dress them. empty is a real state with real copy, not a blank menu: see Empty, loading, error.
React
From @sportingscouter/ui-react. The component adds no visual values of its own — every class comes from the same tv() recipe the design system defines, so the two cannot drift.
import { Select } from '@sportingscouter/ui-react';
<Select
label="Category"
placeholder="Choose a category"
options={[
{ label: 'Course', options: [
{ value: 'water', label: 'Water on course' },
{ value: 'signage', label: 'Signage' },
]},
{ label: 'Village', options: [
{ value: 'bags', label: 'Bag drop' },
{ value: 'medal', label: 'Medal' },
]},
]}
onValueChange={setCategory}
required
/>
{/* Behaviour is Radix, not ours: select.ts is a VISUAL LAYER
ONLY, so the package does not fork opening, focus,
typeahead or portals. */}
<Select label="Rows" scale="sm" options={rows} />theme.css.