Select
Select
Section titled “Select”Persistent single string-value selection with anchored option surface and listbox semantics on Web.
Identity
Section titled “Identity”- Category: Forms & selection
- Status: stable public Registry/export-map component family
- Targets: iOS · Android · Web, subject to the compatibility contract
- Source:
packages/ui/src/components/select.tsx
Import
Section titled “Import”import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@beemvp/beeui-ui';There is no documented deep/private source import. For source ownership from a BeeUI checkout:
pnpm beeui -- add selectRegistry metadata: registry/registry.json.
Composition and public API
Section titled “Composition and public API”- Family exports:
SelectSelectContentSelectGroupSelectItemSelectLabelSelectTriggerSelectValue
Exported types: SelectAlign, SelectCollisionPadding, SelectContentProps, SelectDirection, SelectGroupProps, SelectItemProps, SelectLabelProps, SelectOptionValue, SelectPlacement, SelectProps, SelectTriggerProps, SelectValueProps
The generated API inventory is mechanically joined to packages/ui/src/index.ts, Registry metadata, and the component reference contract. For behavior details and defaults, use the canonical component behavior catalog rather than copying TypeScript declarations into a second hand-maintained table.
State and behavior contract
Section titled “State and behavior contract”Controlled/uncontrolled props, callbacks, disabled semantics, normalization/fail-safe behavior, and mount/unmount rules are defined by the public types and the canonical behavior catalog. The executable fixtures below are the source-grounded usage examples; consumers should not infer state ownership from DOM structure or another UI library.
Provider and dependencies
Section titled “Provider and dependencies”BeeUIProvideris required above this family because it participates in shared overlay/toast runtime infrastructure.- Peer/native dependencies visible to this Registry item:
react,react-native - Registry dependency closure:
core-overlay,overlay-runtime,text,theme,use-direction - Safe-area ownership remains explicit: shell surfaces touching system edges opt into
SafeArea; components do not silently invent app-shell insets. - Web consumers load the BeeUI semantic theme CSS as documented in Web onboarding.
Platform behavior
Section titled “Platform behavior”The same public family is exposed across the supported target matrix; meaningful platform differences remain governed by the compatibility contract.
- Web: live browser/keyboard behavior is verified by Web-specific checks where applicable.
- iOS / Android: package/export/native compile evidence is not described as device-runtime proof. Consult the compatibility and native-preview guides for the exact evidence class.
- Platform-specific or experimental behavior is called out in the canonical component/compatibility docs rather than hidden behind a generic parity claim.
Accessibility
Section titled “Accessibility”Use the Accessibility overview, RTL/localization, and Large text & zoom alongside this family. Roles/states, keyboard/focus behavior, announcements, Dynamic Type/Web zoom, RTL, and reduced-motion expectations remain component-specific; BeeUI does not claim universal accessibility certification from automated tests.
Styling and theming
Section titled “Styling and theming”BeeUI components consume semantic tokens and support the current typed variant/density contracts. Use Theming and Density. className is an implementation escape hatch for source-owned/application work, not a cross-engine portability guarantee.
Executable examples
Section titled “Executable examples”- Primary executable fixture:
apps/showcase/__tests__/dynamic-type-contract.test.tsx - Additional fixture:
apps/showcase/__tests__/helpers/select-anchor-seam.tsx - Additional fixture:
apps/showcase/__tests__/issue-141-rtl-overlay-acceptance.test.tsx - Additional fixture:
apps/showcase/__tests__/perf-overlay-latency.test.tsx
Open the matching Web runtime in Showcase. The Showcase link demonstrates Web behavior; use the native-preview guide for real simulator/emulator/device paths.
Live Web preview
Section titled “Live Web preview”This frame loads the real BeeUI Web Showcase on demand; it is not a second docs-only implementation. It proves browser behavior only. Use native preview for iOS/Android simulator, emulator or device paths.
Composition anatomy
Section titled “Composition anatomy”- Family root / primary export:
Select- Public composition parts / helpers:
SelectContentSelectGroupSelectItemSelectLabelSelectTriggerSelectValue
- Exported type surface:
SelectAlignSelectCollisionPaddingSelectContentPropsSelectDirectionSelectGroupPropsSelectItemPropsSelectLabelPropsSelectOptionValueSelectPlacementSelectPropsSelectTriggerPropsSelectValueProps
- Public composition parts / helpers:
The tree above is ordinary document structure so it remains readable with keyboard and assistive technology; it is derived from the real public export family rather than a canvas-only diagram.
Verified example source
Section titled “Verified example source”The following is the exact typechecked runtime Showcase fixture selected for this live preview: apps/showcase/component-gallery/select-showcase.tsx. Runtime gallery/pattern sources are preferred over test harnesses, and the displayed source and executable source are the same file; there is no separately maintained demo snippet.
import { Box, Button, Card, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogTitle, DialogTrigger, HStack, Section, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, Separator, Text, VStack,} from '@beemvp/beeui-ui';import * as React from 'react';
const SelectConsumerContext = React.createContext('select-context-default');
function SelectContextProbe({ testID }: { testID: string }) { return <Text testID={testID}>{`context: ${React.useContext(SelectConsumerContext)}`}</Text>;}
const LONG_OPTIONS = Array.from({ length: 120 }, (_, index) => ({ label: `Workspace ${String(index + 1).padStart(3, '0')}`, value: `workspace-${index + 1}`,}));
function SelectDismissHierarchyProbe() { const [dialogOpen, setDialogOpen] = React.useState(false); const [dialogSelectOpen, setDialogSelectOpen] = React.useState(false); const [rootSelectOpen, setRootSelectOpen] = React.useState(false);
return ( <VStack gap="sm"> <Button onPress={() => { setRootSelectOpen(true); setDialogOpen(true); setDialogSelectOpen(true); }} testID="select-showcase-scope-open" variant="outline" > Open dismissal hierarchy </Button>
<Select onOpenChange={setRootSelectOpen} open={rootSelectOpen}> <SelectTrigger testID="select-showcase-scope-root-trigger"> <SelectValue placeholder="Root Select" /> </SelectTrigger> <SelectContent testID="select-showcase-scope-root-content"> <SelectItem value="root">Root option</SelectItem> </SelectContent> </Select>
<Dialog onOpenChange={setDialogOpen} open={dialogOpen}> <DialogTrigger testID="select-showcase-scope-dialog-trigger">Scope Dialog</DialogTrigger> <DialogContent> <DialogTitle testID="select-showcase-scope-dialog-title">Dismiss hierarchy</DialogTitle> <DialogDescription> Escape must dismiss this modal-local Select before a root Select behind the Dialog. </DialogDescription> <Select onOpenChange={setDialogSelectOpen} open={dialogSelectOpen}> <SelectTrigger testID="select-showcase-scope-child-trigger"> <SelectValue placeholder="Dialog Select" /> </SelectTrigger> <SelectContent testID="select-showcase-scope-child-content"> <SelectItem value="child">Dialog option</SelectItem> </SelectContent> </Select> <DialogFooter> <DialogClose variant="outline">Close Dialog</DialogClose> </DialogFooter> </DialogContent> </Dialog> </VStack> );}
export function SelectShowcase() { const [controlledValue, setControlledValue] = React.useState('pro');
return ( <SelectConsumerContext.Provider value="preserved"> <VStack gap="lg"> <Card className="gap-5" variant="raised"> <Section description="Select owns persistent option/value semantics. It reuses the anchored overlay runtime but not DropdownMenu command semantics." title="Production Select" > <VStack gap="lg"> <VStack gap="xs"> <Text variant="label">Controlled value</Text> <Select onValueChange={setControlledValue} value={controlledValue}> <SelectTrigger accessibilityLabel="Account plan" testID="select-showcase-controlled-trigger" > <SelectValue placeholder="Choose a plan" testID="select-showcase-controlled-value" /> </SelectTrigger> <SelectContent testID="select-showcase-controlled-content"> <SelectGroup> <SelectLabel>Plans</SelectLabel> <SelectItem testID="select-showcase-controlled-starter" value="starter"> Starter </SelectItem> <SelectItem testID="select-showcase-controlled-pro" value="pro"> Pro </SelectItem> <SelectItem disabled value="enterprise"> Enterprise — invite only </SelectItem> </SelectGroup> </SelectContent> </Select> <Text testID="select-showcase-controlled-state" tone="muted" variant="caption"> {`value: ${controlledValue}`} </Text> </VStack>
<Separator />
<HStack gap="lg" wrap> <VStack className="min-w-52 flex-1" gap="xs"> <Text variant="label">Placeholder / uncontrolled</Text> <Select> <SelectTrigger accessibilityLabel="Project role" testID="select-showcase-placeholder-trigger" > <SelectValue placeholder="Choose a role" testID="select-showcase-placeholder-value" /> </SelectTrigger> <SelectContent testID="select-showcase-placeholder-content"> <SelectItem testID="select-showcase-placeholder-designer" value="designer"> Designer </SelectItem> <SelectItem testID="select-showcase-placeholder-engineer" value="engineer"> Engineer </SelectItem> <SelectItem value="product">Product</SelectItem> </SelectContent> </Select> </VStack>
<VStack className="min-w-52 flex-1" gap="xs"> <Text variant="label">Disabled Select</Text> <Select disabled defaultValue="locked"> <SelectTrigger testID="select-showcase-disabled-trigger"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectItem value="locked">Managed by organization</SelectItem> </SelectContent> </Select> </VStack> </HStack>
<Separator />
<VStack gap="xs"> <Text variant="label">Grouped options</Text> <Select defaultValue="tokyo"> <SelectTrigger accessibilityLabel="Office" testID="select-showcase-group-trigger"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> <SelectLabel>Asia Pacific</SelectLabel> <SelectItem value="tokyo">Tokyo</SelectItem> <SelectItem value="singapore">Singapore</SelectItem> <SelectItem value="sydney">Sydney</SelectItem> </SelectGroup> <SelectGroup> <SelectLabel>Europe</SelectLabel> <SelectItem value="paris">Paris</SelectItem> <SelectItem value="london">London</SelectItem> </SelectGroup> </SelectContent> </Select> </VStack>
<Separator />
<VStack gap="xs"> <Text variant="label">Consumer context through root portal</Text> <Select defaultValue="context"> <SelectTrigger testID="select-showcase-context-trigger"> <SelectValue testID="select-showcase-context-value" /> </SelectTrigger> <SelectContent testID="select-showcase-context-content"> <SelectItem textValue="Context-aware option" value="context"> <SelectContextProbe testID="select-showcase-context-probe" /> </SelectItem> <SelectItem value="plain">Plain option</SelectItem> </SelectContent> </Select> </VStack> </VStack> </Section> </Card>
<Card className="gap-5"> <Section description="The list stays a ScrollView in v1. A 120-option fixture validates viewport max-height, collision, selected-item scrolling, and ordinary press/keyboard selection without adding virtualization." title="Long list" > <Select defaultValue="workspace-118"> <SelectTrigger accessibilityLabel="Workspace" testID="select-showcase-long-trigger"> <SelectValue testID="select-showcase-long-value" /> </SelectTrigger> <SelectContent maxHeight={220} testID="select-showcase-long-content"> {LONG_OPTIONS.map((option, index) => ( <SelectItem key={option.value} testID={ index === 0 ? 'select-showcase-long-first' : index === LONG_OPTIONS.length - 1 ? 'select-showcase-long-last' : undefined } value={option.value} > {option.label} </SelectItem> ))} </SelectContent> </Select> </Section> </Card>
<Card className="gap-5"> <Section description="The same selection API is rendered in a deliberately narrow container and inside Dialog's modal-local overlay host." title="Narrow viewport and Dialog nesting" > <VStack gap="lg"> <Box className="w-full max-w-64" testID="select-showcase-narrow-shell"> <Select defaultValue="very-long-option"> <SelectTrigger accessibilityLabel="Narrow Select" testID="select-showcase-narrow-trigger"> <SelectValue /> </SelectTrigger> <SelectContent testID="select-showcase-narrow-content"> <SelectItem value="short">Short option</SelectItem> <SelectItem value="very-long-option"> A long option label that must truncate safely in a narrow layout </SelectItem> </SelectContent> </Select> </Box>
<Dialog> <DialogTrigger testID="select-showcase-dialog-trigger" variant="outline"> Select inside Dialog </DialogTrigger> <DialogContent> <DialogTitle>Assign owner</DialogTitle> <DialogDescription> Select content resolves against this Dialog's modal-local host while preserving consumer context. </DialogDescription> <Select defaultValue="context-user"> <SelectTrigger accessibilityLabel="Owner" testID="select-showcase-dialog-select-trigger" > <SelectValue testID="select-showcase-dialog-select-value" /> </SelectTrigger> <SelectContent testID="select-showcase-dialog-select-content"> <SelectItem textValue="Context user" value="context-user"> <SelectContextProbe testID="select-showcase-dialog-context-probe" /> </SelectItem> <SelectItem testID="select-showcase-dialog-alex" value="alex" > Alex Morgan </SelectItem> </SelectContent> </Select> <DialogFooter> <DialogClose variant="outline">Done</DialogClose> </DialogFooter> </DialogContent> </Dialog>
<Separator /> <SelectDismissHierarchyProbe /> </VStack> </Section> </Card> </VStack> </SelectConsumerContext.Provider> );}Use the code block’s copy affordance to copy the exact fixture. For a smaller app-specific example, start from the public imports shown above and keep only the state your screen owns.
Limitations
Section titled “Limitations”No component-specific limitation is curated here. Check Compatibility and the linked behavior contract for target-specific constraints.