Select
Show a menu of items that users can select from
Select gives users an accessible, keyboard-navigable list of choices and can adapt its content into a Sheet on smaller screens.
Features
Customizable, themeable default styling
Transitions, themes, and size props
Full-featured, accessible, and keyboard navigable
Shared Sheet handoff with Dialog and Popover
Select provides a dropdown menu for choosing from a list of options. It’s fully accessible with keyboard navigation, supports typeahead search, and automatically stacks above other content.
In v3, Select keeps adapted sheet content mounted through the sheet exit
animation, and web trigger and viewport parts expose data-state="open" | "closed"
for styling.
Select also supports ordered multiple selection across custom web lists, browser-native controls, adapted Sheets, and plain React Native content. The same item registry and value controller power every path.
Installation
Select is already installed in tamagui, or you can install it independently:
yarn
npm
bun
pnpm
For native apps, we recommend setting up native portals to preserve React context inside Select content.
Anatomy
Multiple selection
Pass multiple to use a controlled or uncontrolled string[]. Selecting a new
item appends it. Selecting it again removes it without changing the order of the
remaining values. Multiple selection keeps custom lists and adapted Sheets open.
Select.Value renders registered Select.ItemText labels in selection order,
separated by , . Use renderValue for chips, localized separators, summaries,
or labels that must render before lazy items mount.
Behavior by render path
- A custom floating web Select is an ARIA multi-select listbox. Arrow keys and typeahead move focus. Enter and Space toggle the focused option.
native="web"renders a real<select multiple>. Browser selection, keyboard behavior, and form submission are authoritative.- An adapted Sheet uses the same listbox controller on web and stays open after each toggle. The Sheet closes through its overlay, drag-to-bottom behavior, platform back action, or controlled state. Select does not add a Done row.
- Plain React Native content renders inline when no Adapt target is active. Multiple items expose checkbox-style accessibility state and remain visible after a toggle.
On custom web paths, name renders one root-level hidden input per selected
value, including when the collection is portaled into a Sheet. form can point
those inputs at an external form. The browser-native path puts name and form
on its <select> directly and does not render hidden inputs. React Native does
not render HTML form controls.
API reference
Select
Contains every component for the select:
Props
id
string
Optional for usage with Label.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
Set the size of itself and pass to all inner elements.
children
React.ReactNode
Select children API components.
value
string | string[]
Controlled value. With multiple, this is an ordered string array.
defaultValue
string | string[]
Default value. With multiple, this defaults to an empty array.
multiple
boolean
Default:
falseEnables ordered multiple selection and makes value callbacks array-valued.
onValueChange
(value, details) => void
Cancelable value request. Details identify item-press, keyboard, or native-change.
open
boolean
Controlled open value.
defaultOpen
boolean
Default open value.
onOpenChange
(open: boolean, details) => void
Cancelable open request with the interaction reason and source event.
dir
Direction
Direction of text display.
name
string
Web form field name. Multiple values submit as repeated entries.
form
string
Associates the web form control with an external form id.
native
NativeValue
If passed, will render a native component instead of the custom one. Currently only `web` is supported.
renderValue
(value: string | string[]) => ReactNode
Render function for the selected value. Multiple mode receives the ordered string array. Useful for SSR, lazy mounting, chips, and custom summaries.
lazyMount
boolean
Default:
falseWhen true, defers mounting Select items until opened using React's startTransition. Significantly improves initial render performance for pages with many Selects. Should be combined with `renderValue` for best results.
zIndex
number
z-index for the select portal. Use when select dropdowns need to appear above other portaled content like dialogs or fixed headers. Defaults to automatic stacking (~100000).
Select.Trigger
Extends ListItem to give sizing, icons, and more.
On web it includes data-state="open" | "closed".
Select.Value
Extends Paragraph, adding:
Props
placeholder
string
Optional placeholder to show when no value selected.
Select.Content
Main container for Select content, used to contain the up/down arrows.
Props
onEscapeKeyDown
(event: KeyboardEvent) => void
Called when Escape is pressed while the content is active.
onInteractOutside
(event: Event) => void
Called when pointer or focus interaction happens outside the content.
onPointerDownOutside
(event: Event) => void
Called on outside pointer down. Select composes this with its own preventDefault handling.
onFocusOutside
(event: Event) => void
Called on outside focus. Select composes this with its own preventDefault handling.
Select.ScrollUpButton
Inside Content first, displays when you can scroll up, stuck to the top.
Extends YStack.
Select.ScrollDownButton
Inside Content last, displays when you can scroll down, stuck to the bottom.
Extends YStack.
Select.Viewport
Extends YStack. Contains scrollable content items as children.
On web it includes data-state="open" | "closed".
Props
disableScroll
boolean
Removes ability to scroll and all style and functionality related to scrolling.
unstyled
boolean
Removes all default styles.
Make sure to not pass height prop as that is managed internally because of UX reasons
and having a fixed height will break that behavior.
Select.Group
Extends YStack. Use only when grouping together items, alongside a Label as the first child.
Select.Label
Extends SizableText. Used to label Groups. Includes size-based padding and minHeight for consistent appearance with other Select items.
Select.Separator
Extends Separator. Use inside Select.Group or
Select.Viewport to visually divide option groups.
Select.Item
Extends ListItem. Used to add selectable string values to the list. Item registration order controls keyboard navigation, typeahead, and selection anchoring.
Props
value
string
Provide a value that will be passed on selection.
Select.ItemText
Extends Paragraph. Used inside Item to provide unselectable text that will show above once selected in the parent Select.
Select.Indicator
An animated indicator that highlights the currently focused item. Place it inside Select.Viewport to enable a smooth sliding highlight animation as users navigate through options.
Use the transition prop to control the animation speed. You can use any animation name from your config like quick, quicker, or quickest.
By default, Select uses the item’s hover: and press: clauses for hover feedback. Add
Select.Indicator for a smoother animated effect. If using the indicator, you may want
to set items to have transparent hover styles to avoid visual conflict.
Select.FocusScope
Provides access to the underlying FocusScope component used by Select for focus management. Can be used to control focus behavior from a parent component.
Props
enabled
boolean
Default:
trueWhether focus management is enabled.
loop
boolean
Default:
falseWhen true, tabbing from last item will focus first tabbable and shift+tab from first item will focus last tabbable.
trapped
boolean
Default:
falseWhen true, focus cannot escape the focus scope via keyboard, pointer, or programmatic focus.
noFocus
boolean
Default:
falseZero focus mode. While active, focus is allowed neither inside nor outside the scope. Web only.
focusOnIdle
boolean | number
Default:
trueWhen true, waits for idle before focusing. When a number, waits that many ms. This prevents reflows during animations.
onMountAutoFocus
(event: Event) => void
Event handler called when auto-focusing on mount. Can be prevented.
onUnmountAutoFocus
(event: Event) => void
Event handler called when auto-focusing on unmount. Can be prevented.
Performance
For pages with many Select components, you can significantly improve initial render performance by using the lazyMount prop combined with renderValue:
How it works:
lazyMountdefers mounting all Select items until the dropdown is first opened- The mount happens inside React’s
startTransition, keeping the trigger responsive renderValueprovides the display text synchronously, avoiding the need to mount items just to show the selected value- Once mounted, items stay mounted for fast subsequent opens
This is especially useful when rendering many Selects on a single page, as each Select with 20+ items would otherwise mount all those items on initial page load.
Adapted Sheet
When used alongside <Adapt />, Select will render as a sheet when that breakpoint is active. See Adapt for how the handoff works.
This is the only way to render a Select on Native for now, as mobile apps tend to show Select very differently from web and Tamagui wants to present the right abstractions for each platform.
See Sheet for more props.
Use Adapt.Contents inside Sheet.Container to insert the contents given to
Select.Content.
Source
v2-look Select: styled trigger/value/icon, viewport with shadow, items with highlight + check indicator, scroll buttons and separators, over the unstyled @tamagui/ui Select behavior. Adapts to a Sheet on native. This is the exact source the registry ships — copy it into your app and the examples above import from your copy.
components/tamagui/Select.tsxDependencies
yarn add @tamagui/core @tamagui/select @tamagui/textExpects theme tokens: background, background-hover, background-press, background-focus, border-color, border-color-hover, outline-color, color, color-10. Native: requires a Portal/Adapt provider at the app root; on native the Select adapts to a Sheet, so the Sheet native peer requirements apply when adaptation is used
Need raw behavior without any skin? tamagui/unstyled re-exports the @tamagui/ui primitives (advanced).