Select
Show a menu of items users can select from one of
import { Check, ChevronDown, ChevronUp } from '@tamagui/lucide-icons'import { useMemo, useState } from 'react'import type { FontSizeTokens, SelectProps } from 'tamagui'import { Adapt, Label, Select, Sheet, XStack, YStack, getFontSize } from 'tamagui'import { LinearGradient } from 'tamagui/linear-gradient'export function SelectDemo() {return (<YStack gap="$4"><XStack ai="center" gap="$4"><Label htmlFor="select-demo-1" f={1} miw={80}>Custom</Label><SelectDemoItem id="select-demo-1" /></XStack><XStack ai="center" gap="$4"><Label htmlFor="select-demo-2" f={1} miw={80}>Native</Label><SelectDemoItem id="select-demo-2" native /></XStack></YStack>)}export function SelectDemoItem(props: SelectProps) {const [val, setVal] = useState('apple')return (<Select value={val} onValueChange={setVal} disablePreventBodyScroll {...props}><Select.Trigger width={220} iconAfter={ChevronDown}><Select.Value placeholder="Something" /></Select.Trigger><Adapt when="sm" platform="touch"><Sheet native={!!props.native} modal dismissOnSnapToBottom animationConfig={{ type: 'spring', damping: 20, mass: 1.2, stiffness: 250, }} ><Sheet.Frame><Sheet.ScrollView><Adapt.Contents /></Sheet.ScrollView></Sheet.Frame><Sheet.Overlay animation="lazy" enterStyle={{ opacity: 0 }} exitStyle={{ opacity: 0 }} /></Sheet></Adapt><Select.Content zIndex={200000}><Select.ScrollUpButton alignItems="center" justifyContent="center" position="relative" width="100%" height="$3" ><YStack zIndex={10}><ChevronUp size={20} /></YStack><LinearGradient start={[0, 0]} end={[0, 1]} fullscreen colors={['$background', 'transparent']} borderRadius="$4" /></Select.ScrollUpButton><Select.Viewport // to do animations: // animation="quick" // animateOnly={['transform', 'opacity']} // enterStyle={{ o: 0, y: -10 }} // exitStyle={{ o: 0, y: 10 }} minWidth={200} ><Select.Group><Select.Label>Fruits</Select.Label>{/* for longer lists memoizing these is useful */}{useMemo(() =>items.map((item, i) => {return (<Select.Item index={i} key={item.name} value={item.name.toLowerCase()} ><Select.ItemText>{item.name}</Select.ItemText><Select.ItemIndicator marginLeft="auto"><Check size={16} /></Select.ItemIndicator></Select.Item>)}),[items])}</Select.Group>{/* Native gets an extra icon */}{props.native && (<YStack position="absolute" right={0} top={0} bottom={0} alignItems="center" justifyContent="center" width={'$4'} pointerEvents="none" ><ChevronDown size={getFontSize((props.size as FontSizeTokens) ?? '$true')} /></YStack>)}</Select.Viewport><Select.ScrollDownButton alignItems="center" justifyContent="center" position="relative" width="100%" height="$3" ><YStack zIndex={10}><ChevronDown size={20} /></YStack><LinearGradient start={[0, 0]} end={[0, 1]} fullscreen colors={['transparent', '$background']} borderRadius="$4" /></Select.ScrollDownButton></Select.Content></Select>)}const items = [{ name: 'Apple' },{ name: 'Pear' },{ name: 'Blackberry' },{ name: 'Peach' },{ name: 'Apricot' },{ name: 'Melon' },{ name: 'Honeydew' },{ name: 'Starfruit' },{ name: 'Blueberry' },{ name: 'Raspberry' },{ name: 'Strawberry' },{ name: 'Mango' },{ name: 'Pineapple' },{ name: 'Lime' },{ name: 'Lemon' },{ name: 'Coconut' },{ name: 'Guava' },{ name: 'Papaya' },{ name: 'Orange' },{ name: 'Grape' },{ name: 'Jackfruit' },{ name: 'Durian' },]
Features
Comes with styling, yet completely customizable and themeable.
Accepts animations, themes, size props and more.
Accessible, keyboard navigable, full-featured.
Installation
Select is already installed in tamagui
, or you can install it independently:
yarn add @tamagui/select
Anatomy
import { Select } from 'tamagui' // or '@tamagui/select'export default () => (<Select defaultValue=""><Select.Trigger><Select.Value placeholder="Search..." /></Select.Trigger><Select.Content><Select.ScrollUpButton /><Select.Viewport><Select.Group><Select.Label /><Select.Item><Select.ItemText /></Select.Item></Select.Group></Select.Viewport><Select.ScrollDownButton /></Select.Content></Select>)
Note that Select only works on Native using the Adapt component to adapt it to a Sheet. See below for docs.
API Reference
Select
Contains every component for the select:
Props
id
string
Optional for usage with Label
size
SizeTokens
Set the size of itself and pass to all inner elements
children
React.ReactNode
Select children API components
value
string
Controlled value
defaultValue
string
Default value
onValueChange
(value: string) => void
Callback on value change
open
boolean
Controlled open value
defaultOpen
boolean
Default open value
onOpenChange
(open: boolean) => void
Callback on open change
dir
Direction
Direction of text display
name
string
For use in forms
native
NativeValue
If passed, will render a native component instead of the custom one. Currently only `web` is supported.
Select.Trigger
Extends ListItem to give sizing, icons, and more.
Select.Value
Extends Paragraph, adding:
Props
placeholder
string
Optional placeholder to show when no value selected
SelectContent
Main container for Select content, used to contain the up/down arrows, no API beyond children.
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 ThemeableStack. Contains scrollable content items as children.
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 behaviour
Select.Group
Extends YStack. Use only when grouping together items, alongside a Label as the first child.
Select.Label
Extends ListItem. Used to label Groups.
Select.Item
Extends ListItem. Used to add selectable values ot the list. Must provide an index as React Native doesn't give any escape hatch for us to configure that automatically.
Props
index (required)
number
Incrementally starting from 0, matching its appearance in the list.
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.Sheet
When used alongside <Adapt />
, Select will render as a sheet when that breakpoint is active.
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.
Must use Select.SheetContents
inside the Select.Sheet.Frame
to insert the contents given to Select.Content
import { Select } from 'tamagui' // or '@tamagui/select'export default () => (<Select defaultValue=""><Select.Trigger><Select.Value placeholder="Search..." /></Select.Trigger><Adapt when="sm" platform="touch">{/* or <Select.Sheet> */}<Sheet><Sheet.Frame><SheetContents /></Sheet.Frame><Sheet.Overlay /></Sheet></Adapt><Select.Content><Select.ScrollUpButton /><Select.Viewport><Select.Group><Select.Label /><Select.Item><Select.ItemText /></Select.Item></Select.Group></Select.Viewport><Select.ScrollDownButton /></Select.Content></Select>)
Previous
RadioGroup
Next
Slider