Native Select
tetra-ui/native-selectFreeComponent
A native single-selection input built on Expo UI Picker. Always compose with Content; optionally add Trigger and Input for a form-styled field or custom trigger. Content opens a wheel bottom sheet on iOS and ExposedDropdownMenuBox on Android.
Live preview
live · rendered by the registry
Rendered by tetra-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://tetra-ui.com/r/native-select.jsonSource
1import {2 type PickerAppearance,3 type PickerItemValue,4 Picker as PickerPrimitive,5} from "@expo/ui";6import {7 Children,8 createContext,9 isValidElement,10 useCallback,11 useContext,12 useEffect,13 useLayoutEffect,14 useMemo,15 useState,16} from "react";17import {18 type GestureResponderEvent,19 Platform,20 Pressable,21 type PressableProps,22 View,23} from "react-native";24import Animated, {25 Easing,26 interpolate,27 useAnimatedStyle,28 useSharedValue,29 withTiming,30} from "react-native-reanimated";31import { cn } from "@/lib/utils";32import { ActionInput } from "../action-input";33import {34 BottomSheet,35 BottomSheetBody,36 BottomSheetContent,37 BottomSheetFooter,38 BottomSheetHeader,39 BottomSheetTitle,40} from "../bottom-sheet";41import { ChevronDownIcon } from "../icons";42import {43 InputAddon,44 type InputAddonChild,45 type InputAddonChildren,46 InputAddonIcon,47 useInputAddons,48} from "../input";49import { Slot } from "../slot";50import {51 NativeSelectAndroidHost,52 NativeSelectContentMenu,53 NativeSelectTriggerAnchor,54} from "./native-select-input";55import { NativeSelectPicker } from "./native-select-picker";5657// Constants58const ANIMATION_DURATION = 280;59const ANIMATION_EASING = Easing.out(Easing.cubic);60const NATIVE_SELECT_INPUT_NAME = "NativeSelectInput";61const NATIVE_SELECT_TRIGGER_NAME = "NativeSelectTrigger";62const NATIVE_SELECT_CONTENT_NAME = "NativeSelectContent";63const NATIVE_SELECT_SHEET_FOOTER_NAME = "NativeSelectSheetFooter";64const WHEEL_PICKER_HEIGHT = 216;65const DEFAULT_PLACEHOLDER = "Select...";6667type NativeSelectVariant = PickerAppearance;6869// Types70type NativeSelectItemData<T extends PickerItemValue> = {71 label: string;72 value: T;73};7475type NativeSelectContextProps<T extends PickerItemValue> = {76 open: boolean;77 onOpenChange: (open: boolean) => void;78 value?: T;79 onValueChange: (value: T) => void;80 selectedValue?: T;81 setSelectedValue: (value: T) => void;82 onConfirm: (value?: T) => void;83 onCancel: () => void;84 disabled?: boolean;85 items: NativeSelectItemData<T>[];86 itemElements: React.ReactElement[];87 setItemElements: (elements: React.ReactElement[]) => void;88 placeholder: string;89 setPlaceholder: (placeholder: string) => void;90 variant: NativeSelectVariant;91 setVariant: (variant: NativeSelectVariant) => void;92 hasTrigger: boolean;93 hasInput: boolean;94 className?: string;95 testID?: string;96};9798type NativeSelectProps<T extends PickerItemValue> = {99 open?: boolean;100 onOpenChange?: (open: boolean) => void;101// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from tetra-ui
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | tetra-ui | Components | Free | 1 dep | |
| Action Inputaction-input | tetra-ui | Components | Free | no deps | |
| Alertalert | tetra-ui | Components | Free | no deps | |
| Avataravatar | tetra-ui | Components | Free | no deps | |
| Badgebadge | tetra-ui | Components | Free | no deps | |
| Bottom Sheetbottom-sheet | tetra-ui | Components | Free | 4 deps · 7 files | |
| Buttonbutton | tetra-ui | Components | Free | no deps | |
| Cardcard | tetra-ui | Components | Free | no deps |
