# tetra-ui — Full reference for AI agents > shadcn/ui-style copy-paste components for React Native. Expo + Uniwind + New Architecture. Website: https://tetra-ui.com GitHub: https://github.com/Liamandrew/tetra-ui Registry: https://tetra-ui.com/r/{name}.json Registry index: https://tetra-ui.com/r/registry.json --- ## Overview tetra-ui is a component registry for React Native — not a traditional npm UI library. Components are copied into your project with the shadcn CLI. You own and customize the source code. Philosophy: 1. Add components with CLI: `npx shadcn@latest add @tetra-ui/button` 2. Own the source — files live in your repo 3. Mobile-native defaults — touch-first, accessible, platform-aware ### Requirements - React 19 - React Native New Architecture (required) - Uniwind for Tailwind-style styling - Expo recommended ### When to use tetra-ui Use tetra-ui when: - You use or want shadcn/ui's copy-paste workflow on React Native - You build with Expo and Uniwind/Tailwind - You want purpose-built mobile UI, not universal web+native abstractions - You need native primitives like Expo UI Menu and bottom sheets Consider alternatives when: - You need one package for web and native (Tamagui, etc.) - You want the largest component catalog (React Native Reusables, AniUI, native-shadcn) --- ## Installation ### 1. Install Uniwind Follow https://docs.uniwind.dev/ to add Uniwind to your React Native/Expo project. ### 2. Install utilities ```bash npm install class-variance-authority clsx tailwind-merge ``` ### 3. TypeScript paths ```json { "compilerOptions": { "paths": { "@/*": ["./*"] } } } ``` ### 4. Theme tokens in globals.css Import tailwind and uniwind, then add theme CSS variables for light/dark variants. Full CSS block: https://tetra-ui.com/docs/installation Key tokens: `--background`, `--foreground`, `--primary`, `--secondary`, `--muted`, `--accent`, `--destructive`, `--border`, `--input`, `--ring`, `--radius` ### 5. cn() helper ```ts // lib/utils.ts import { type ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } export function mergeRefs(...refs: (React.Ref | undefined)[]) { return (value: T) => { for (const ref of refs) { if (typeof ref === "function") { ref(value); } else if (ref) { ref.current = value; } } }; } ``` ### 6. components.json ```json { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": false, "tsx": true, "tailwind": { "config": "", "css": "src/global.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "iconLibrary": "lucide", "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components", "lib": "@/lib", "hooks": "@/hooks" }, "registries": { "@tetra-ui": "https://tetra-ui.com/r/{name}.json" } } ``` ### 7. Add components ```bash npx shadcn@latest add @tetra-ui/button ``` --- ## Agent rules - Always add components via `npx shadcn@latest add @tetra-ui/{name}` — do not generate from memory - Import from `@/components/ui/{name}` (or user's configured alias) - Use React Native primitives (View, Text, Pressable) — never DOM elements - Style with `className` + Uniwind — not StyleSheet - Text children must be styled directly; no CSS cascade on native - Check component docs before implementing: https://tetra-ui.com/docs/components/{name} --- ## Components Install: `npx shadcn@latest add @tetra-ui/{name}` ### accordion A vertically stacked set of interactive headings that reveal associated content sections. Docs: https://tetra-ui.com/docs/components/accordion Deps: react-native-reanimated Registry deps: icons, slot ### action-input A component that allows a user to trigger an action and displays a value attached to the action. Docs: https://tetra-ui.com/docs/components/action-input Registry deps: icons, input ### badge Displays a badge. Docs: https://tetra-ui.com/docs/components/badge ### bottom-sheet Interactive bottom sheet built on Expo UI with native snap points, gestures, and keyboard support. Docs: https://tetra-ui.com/docs/components/bottom-sheet Deps: @expo/ui, react-native-reanimated, react-native-keyboard-controller, react-native-safe-area-context Registry deps: button, icons, slot ### button A component to display a button and allows a user to trigger an action. Docs: https://tetra-ui.com/docs/components/button Exports: Button, ButtonText, ButtonIcon Variants: default, secondary, destructive, outline, ghost, link Sizes: default, sm, lg, icon, icon-sm, icon-lg Props: busy (loading state), disabled Usage: ```tsx import { Button, ButtonText, ButtonIcon } from "@/components/ui/button"; ``` ### card Displays a card with a header, content, and footer. Docs: https://tetra-ui.com/docs/components/card Exports: Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter ### checkbox A control that allows users to toggle between checked and unchecked states. Docs: https://tetra-ui.com/docs/components/checkbox Deps: react-native-reanimated Registry deps: icons, input ### choicebox A group of selectable cards for single or multiple choice. Docs: https://tetra-ui.com/docs/components/choicebox Registry deps: checkbox, input, radio, stack Exports: Choicebox, ChoiceboxItem, ChoiceboxItemHeader, ChoiceboxItemTitle, ChoiceboxItemDescription, ChoiceboxIndicator ### chip Displays a compact, rounded chip element. Docs: https://tetra-ui.com/docs/components/chip ### empty Displays an empty state. Docs: https://tetra-ui.com/docs/components/empty Registry deps: text ### form Components and utilities that help you compose forms with react-hook-form. Docs: https://tetra-ui.com/docs/components/form Deps: react-hook-form Registry deps: label Exports: Form, FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription ### heading A component to display headings. Docs: https://tetra-ui.com/docs/components/heading ### icons Icon components styled with Tailwind classes for React Native. Docs: https://tetra-ui.com/docs/components/icons Deps: react-native-svg ### inline-list A grouped list section for settings-style rows with flexible leading and trailing addons. Docs: https://tetra-ui.com/docs/components/inline-list Registry deps: text Exports: InlineList, InlineListItem, InlineListItemTitle, InlineListItemDescription, InlineListItemAddon, InlineListItemAddonIcon, useInlineListItemAddons Props (InlineList): title (optional section heading) Props (InlineListItem): onPress (makes row pressable), showSeparator (default: true except last item), disabled, variant ("default" | "destructive") Props (InlineListItemAddon): align ("inline-start" | "inline-end") Separators between items are inserted automatically with a left inset. Pass a string as InlineListItem children for a title-only row. Omit onPress for static rows (e.g. trailing Switch). Compose Radio or Checkbox in an inline-end addon for selection rows. Usage: ```tsx import { InlineList, InlineListItem, InlineListItemAddon, InlineListItemAddonIcon, InlineListItemDescription, InlineListItemTitle, } from "@/components/ui/inline-list"; import { ChevronRightIcon, ShieldIcon } from "@/components/ui/icons"; {}}> Personal Info Name, email, phone number {}}> Two-Factor Auth ``` Static row with Switch: ```tsx Notifications ``` Destructive row: ```tsx {}} variant="destructive"> Delete Account ``` ### input A core component that allows users to enter text. Docs: https://tetra-ui.com/docs/components/input Deps: react-native-reanimated Registry deps: button ### label A label component used to accompany form inputs. Docs: https://tetra-ui.com/docs/components/label ### menu A composable native menu built on Expo UI, with support for groups, separators, and nested submenus. Docs: https://tetra-ui.com/docs/components/menu Deps: @expo/ui, @expo/material-symbols ### native-select A native single-selection input built on Expo UI Picker. Always compose with NativeSelectContent. Content-only for inline menu/wheel; Trigger + Input for form-styled field (iOS: wheel bottom sheet or menu in input; Android: ExposedDropdownMenuBox). Docs: https://tetra-ui.com/docs/components/native-select Deps: @expo/ui, react-native-reanimated Registry deps: action-input, bottom-sheet, icons, input ### native-date-select A native date/time input built on Expo UI DatePicker (iOS) and DateTimePicker (Android). Always compose with NativeDateSelectContent. Content-only for inline picker; Trigger + Input for form-styled field (iOS: wheel bottom sheet or compact in input; Android: Material dialogs). Docs: https://tetra-ui.com/docs/components/native-date-select Deps: @expo/ui, react-native-reanimated Registry deps: action-input, bottom-sheet, icons, input ### otp-input A component for entering one-time passwords with individual character slots. API mirrors shadcn Input OTP (`InputOTP` → `OTPInput`). Docs: https://tetra-ui.com/docs/components/otp-input Deps: react-native-reanimated Registry deps: input, text Exports: OTPInput, OTPInputGroup, OTPInputSlot, OTPInputSeparator, OTPInputSlotPlaceholder, OTPInputSlotValue, OTPInputSlotCaret, useOTPInput, useOTPInputSlot, REGEXP_ONLY_DIGITS, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS_AND_CHARS Props: maxLength (required), value, defaultValue, onChange, onComplete, disabled, invalid, pattern, inputMode, placeholder, secureTextEntry, onFocus, onBlur Ref: focus(), blur(), clear(), setValue(value) Usage: ```tsx import { OTPInput, OTPInputGroup, OTPInputSeparator, OTPInputSlot, } from "@/components/ui/otp-input"; console.log(code)}> ``` PIN (secure): ```tsx ``` ### password-input An input component that allows users to enter a password. Docs: https://tetra-ui.com/docs/components/password-input Registry deps: icons, input, text-input ### popover Displays content in a portal relative to the triggering button element. Docs: https://tetra-ui.com/docs/components/popover Deps: react-native-reanimated, react-native-safe-area-context Registry deps: portal, slot ### progress Displays an indicator showing the completion progress of a task. Docs: https://tetra-ui.com/docs/components/progress Deps: react-native-reanimated Registry deps: text ### radio A control that indicates a selected option within a group. Docs: https://tetra-ui.com/docs/components/radio Deps: react-native-reanimated ### portal Renders children into a different part of the app. Docs: https://tetra-ui.com/docs/components/portal Deps: react-native-screens ### search-input An input component that allows users to search for content. Docs: https://tetra-ui.com/docs/components/search-input Registry deps: icons, input ### select A component that allows users to select a value from a list of options. Docs: https://tetra-ui.com/docs/components/select Deps: react-native-reanimated Registry deps: action-input, bottom-sheet, icons, input, popover, slot, text ### separator Divides content with a horizontal or vertical line. Docs: https://tetra-ui.com/docs/components/separator ### skeleton A component to display placeholder content while in a loading state. Docs: https://tetra-ui.com/docs/components/skeleton Deps: react-native-reanimated ### slider A control for selecting a value from a continuous or stepped range. Docs: https://tetra-ui.com/docs/components/slider Deps: @expo/ui ### slot A utility component that allows merging props onto an optional child component. Docs: https://tetra-ui.com/docs/components/slot ### stack A layout component that stacks children horizontally or vertically with consistent spacing. Docs: https://tetra-ui.com/docs/components/stack ### switch A control that allows users to toggle between checked and unchecked states. Docs: https://tetra-ui.com/docs/components/switch Deps: @expo/ui ### swipeable Swipe leading and trailing actions onto row content. Compositional wrapper around ReanimatedSwipeable. Docs: https://tetra-ui.com/docs/components/swipeable Deps: react-native-gesture-handler, react-native-reanimated Exports: SwipeableList, useSwipeableList, Swipeable, SwipeableContent, SwipeableActionGroup, SwipeableAction, SwipeableActionText, SwipeableActionIcon Requires `GestureHandlerRootView` (included in tetra-ui ThemeProvider). Usage: ```tsx import { Swipeable, SwipeableAction, SwipeableActionGroup, SwipeableContent, SwipeableList, } from "@/components/ui/swipeable"; import { InlineList, InlineListItem, InlineListItemTitle, } from "@/components/ui/inline-list"; Message from Expo {}}>Pin {}}> Delete ``` ### text A lightweight wrapper around the React Native Text component to provide default styles. Docs: https://tetra-ui.com/docs/components/text ### text-input A component that allows users to enter text. Docs: https://tetra-ui.com/docs/components/text-input Registry deps: input ### textarea-input A component that allows users to enter larger text. Docs: https://tetra-ui.com/docs/components/textarea-input ### toast An opinionated toast component for React Native. Built on sonner-native. Docs: https://tetra-ui.com/docs/components/toast Deps: sonner-native, react-native-gesture-handler, react-native-reanimated, react-native-safe-area-context, react-native-screens, react-native-svg, react-native-worklets Registry deps: icons, text Exports: Toaster, toast Setup: add `` to your root layout (e.g. `app/_layout.tsx`). Usage: ```tsx import { Toaster, toast } from "@/components/ui/toast"; toast("Event has been created."); toast.success("Event has been created."); toast.error("Event has not been created."); toast.promise(fetchData(), { loading: "Loading...", success: "Data loaded", error: "Failed to load data", }); ``` --- ## Common recipes ### Login form Install: `npx shadcn@latest add @tetra-ui/form @tetra-ui/text-input @tetra-ui/password-input @tetra-ui/button @tetra-ui/label` Use Form + FormField + TextInput + PasswordInput + Button with react-hook-form and zod. ### Settings screen Install: `npx shadcn@latest add @tetra-ui/inline-list @tetra-ui/switch @tetra-ui/radio @tetra-ui/icons @tetra-ui/stack` Use InlineList + InlineListItem with Switch/Radio in addons for settings rows. For swipe actions on rows, also add `@tetra-ui/swipeable`. Use InlineList for grouped settings rows (automatic separators, optional section titles). Stack multiple InlineList sections. Use Switch in static rows, Radio in pressable selection rows, and InlineListItemAddon for leading icons or trailing chevrons. ### Bottom sheet picker Install: `npx shadcn@latest add @tetra-ui/select` Select uses bottom-sheet on mobile automatically for custom option lists. For a form-styled native picker, use `npx shadcn@latest add @tetra-ui/native-select` with `NativeSelectTrigger`, `NativeSelectInput`, and `NativeSelectContent` (iOS: wheel in a bottom sheet; Android: platform dropdown). ### Verification code (OTP) Install: `npx shadcn@latest add @tetra-ui/otp-input @tetra-ui/form @tetra-ui/label` Use OTPInput with grouped slots for 6-digit codes, or `secureTextEntry` for 4-digit PINs. Wrap in Field + FieldControl for labels and validation errors. ```tsx import { Field, FieldControl, FieldErrorMessage, FieldLabel, } from "@/components/ui/form"; import { OTPInput, OTPInputGroup, OTPInputSeparator, OTPInputSlot, } from "@/components/ui/otp-input"; Verification code ``` --- ## Key differences from web shadcn/ui - Uniwind instead of Tailwind CSS on DOM - No CSS cascade — style Text elements directly - No data-* attributes for variants - Portals use react-native-screens, not DOM portals - Reanimated for animations - Some controls use Expo UI for native platform behavior (Menu, Switch, Slider) - Icons via lucide-react-native with styled wrapper --- ## Links - Docs: https://tetra-ui.com/docs - Installation: https://tetra-ui.com/docs/installation - Components: https://tetra-ui.com/docs/components - Changelog: https://tetra-ui.com/docs/changelog - llms.txt: https://tetra-ui.com/llms.txt - AGENTS.md: https://github.com/Liamandrew/tetra-ui/blob/main/AGENTS.md