Components
A collection of accessible, styled primitives built with React Native and Tailwind CSS.
Collapsible content sections.
User profile images and fallbacks.
Modal sheet sliding from bottom.
Interactive button with variants.
Toggle selection control.
Layout wrappers and safe areas.
SVG icon wrapper.
Optimized image component.
Image with error handling & fallbacks.
Text input with validation.
Keyboard-aware form container.
Linear and circular progress.
Single selection control.
Dropdown selection options.
Visual divider.
Layout primitives (HStack, VStack).
Toggle switch control.
Typography component.
Animated view wrapper.
Accordion
A collapsible component that displays a list of sections.
1import { Accordion, Text } from '@/components/ui';2import { useState } from 'react';3import { View } from 'react-native';45const SECTIONS = [6 { title: 'Section 1', content: 'Content for section 1' },7 { title: 'Section 2', content: 'Content for section 2' },8];910export default function AccordionExample() {11 const [activeSections, setActiveSections] = useState<number[]>([]);1213 return (14 <Accordion15 sections={SECTIONS}16 activeSections={activeSections}17 onChange={setActiveSections}18 renderHeader={(section, index, isActive) => (19 <View className={`p-4 ${isActive ? 'bg-neutral-100 dark:bg-neutral-800' : 'bg-white dark:bg-black'}`}>20 <Text className="font-bold">{section.title}</Text>21 </View>22 )}23 renderContent={(section) => (24 <View className="p-4 bg-neutral-50 dark:bg-neutral-900">25 <Text>{section.content}</Text>26 </View>27 )}28 />29 );30}
Avatar
Displays an image or a fallback with initials for a user.
1import { Avatar } from '@/components/ui';2import { View } from 'react-native';34export default function AvatarExample() {5 return (6 <View className="flex-row gap-4 items-center">7 {/* With Image */}8 <Avatar9 source={{ uri: "https://github.com/shadcn.png" }}10 size="lg"11 />1213 {/* With Initials */}14 <Avatar15 label="Jane Doe"16 size="md"17 className="bg-blue-500"18 />1920 {/* Different Shapes */}21 <Avatar22 label="JD"23 size="md"24 shape="square"25 className="bg-green-500"26 />27 </View>28 );29}
Bottom Sheet
A modal sheet that slides up from the bottom of the screen.
1import { BottomSheet, Button, Text, useBottomSheet } from '@/components/ui';2import { View } from 'react-native';34export default function BottomSheetExample() {5 const { ref, present, dismiss } = useBottomSheet();67 return (8 <>9 <Button onPress={present} label="Open Sheet" />1011 <BottomSheet12 ref={ref}13 title="Options"14 detents={["auto", 0.6, 1]}15 >16 <View className="p-4 gap-4">17 <Text>Here is some content inside the sheet.</Text>18 <Button variant="outline" onPress={dismiss} label="Close" />19 </View>20 </BottomSheet>21 </>22 );23}
Checkbox
A control that allows the user to toggle between checked and unchecked states.
1import { Checkbox } from '@/components/ui';2import { useState } from 'react';34export default function CheckboxExample() {5 const [checked, setChecked] = useState(false);67 return (8 <Checkbox9 checked={checked}10 onChange={setChecked}11 label="Accept terms and conditions"12 accessibilityLabel="Terms checkbox"13 />14 );15}
Container
Layout wrappers for consistent padding and safe area handling.
1import { Container, Text } from '@/components/ui';23export default function ContainerExample() {4 return (5 // Container.Insets handles safe area insets6 <Container.Insets>7 {/* Container.Page provides standard page background and flex */}8 <Container.Page>9 <Text>Page Content</Text>1011 {/* Container.Box provides standard padding */}12 <Container.Box>13 <Text>Boxed Content</Text>14 </Container.Box>15 </Container.Page>16 </Container.Insets>17 );18}
Icon
A wrapper for displaying icons from image sources or SVGs.
1import { Icon } from '@/components/ui';23export default function IconExample() {4 return (5 <Icon6 icon={require("@/assets/icon.png")}7 size={32}8 className="text-blue-500"9 />10 );11}
Image
An optimized image component using expo-image with styling support.
1import { Image } from '@/components/ui';23export default function ImageExample() {4 return (5 <Image6 source={{ uri: "https://picsum.photos/200" }}7 className="w-40 h-40 rounded-xl"8 contentFit="cover"9 transition={1000}10 />11 );12}
Safe Fast Image
A wrapper around Image that handles loading errors by showing a fallback image. It also supports blurhash placeholders and safe source validation.
1import { SafeFastImage } from '@/components/ui';23export default function SafeFastImageExample() {4 return (5 <SafeFastImage6 source={{ uri: "https://invalid-url.com/image.png" }}7 className="w-40 h-40 rounded-xl"8 contentFit="cover"9 placeholder="L6PZfSi_.AyE_3t7t7R**0o#DgR4" // blurhash10 transition={1000}11 // If the source fails or is invalid, a default fallback icon is shown12 />13 );14}
Input
Text input component with labels, error states, and icons. Supports integration with React Hook Form and Zod validation.
Basic Usage
1import { Input } from '@/components/ui';2import { useState } from 'react';34export default function InputExample() {5 const [value, setValue] = useState("");67 return (8 <Input9 label="Email Address"10 placeholder="hello@example.com"11 value={value}12 onChangeText={setValue}13 error={value.length > 0 && !value.includes('@') ? "Invalid email" : undefined}14 />15 );16}
Variants
1import { Input, Icon } from '@/components/ui';2import { Mail, Lock } from 'lucide-react-native';34// ... inside component5<Input6 label="With Left Icon"7 leftIcon={<Icon icon={Mail} size={20} className="text-neutral-500" />}8 placeholder="Email"9/>1011<Input12 label="With Right Icon"13 rightIcon={<Icon icon={Lock} size={20} className="text-neutral-500" />}14 secureTextEntry15 placeholder="Password"16/>1718<Input19 label="Disabled Input"20 value="Cannot change me"21 editable={false}22 disabled23/>2425<Input26 label="Multiline Area"27 multiline28 numberOfLines={4}29 className="h-32"30 textAlignVertical="top"31/>
Form Integration (Zod + React Hook Form)
Use ControlledInput for seamless integration with react-hook-form.
1import { ControlledInput, Button, VStack } from '@/components/ui';2import { useForm } from 'react-hook-form';3import { z } from 'zod';4import { zodResolver } from '@hookform/resolvers/zod';56const schema = z.object({7 email: z.string().email({ message: "Invalid email address" }),8 password: z.string().min(6, { message: "Password must be at least 6 characters" }),9});1011type FormData = z.infer<typeof schema>;1213export default function FormExample() {14 const { control, handleSubmit } = useForm<FormData>({15 resolver: zodResolver(schema),16 defaultValues: {17 email: '',18 password: '',19 },20 });2122 const onSubmit = (data: FormData) => {23 console.log("Form Submitted:", data);24 };2526 return (27 <VStack className="gap-4">28 <ControlledInput29 control={control}30 name="email"31 label="Email"32 placeholder="hello@example.com"33 autoCapitalize="none"34 keyboardType="email-address"35 />3637 <ControlledInput38 control={control}39 name="password"40 label="Password"41 secureTextEntry42 placeholder="••••••"43 />4445 <Button onPress={handleSubmit(onSubmit)} label="Login" />46 </VStack>47 );48}
Input View
A scrollable container that automatically handles keyboard avoidance using react-native-avoid-softinput. Perfect for forms.
1import { InputView, Input, Button, Text } from '@/components/ui';23export default function InputViewExample() {4 return (5 // InputView handles keyboard avoidance and scrolling automatically6 <InputView contentContainerClassName="p-4 gap-4">7 <Text className="text-2xl font-bold mb-4">Registration</Text>89 <Input label="First Name" placeholder="John" />10 <Input label="Last Name" placeholder="Doe" />11 <Input label="Email" placeholder="john@example.com" />12 <Input label="Phone" placeholder="+1 234 567 8900" />13 <Input label="Address" placeholder="123 Main St" multiline numberOfLines={3} />1415 <Button label="Submit" className="mt-4" onPress={() => {}} />16 </InputView>17 );18}
Progress Bar
Visual indicator of progress, available in linear and circular forms.
1import { ProgressBar, Button, VStack } from '@/components/ui';2import { useRef } from 'react';34export default function ProgressBarExample() {5 const linearRef = useRef(null);6 const circularRef = useRef(null);78 const updateProgress = () => {9 linearRef.current?.setProgress(75);10 circularRef.current?.setProgress(75);11 };1213 return (14 <VStack className="gap-8">15 <ProgressBar ref={linearRef} initialProgress={30} />1617 <ProgressBar.Circular18 ref={circularRef}19 initialProgress={30}20 size={60}21 />2223 <Button onPress={updateProgress} label="Set to 75%" />24 </VStack>25 );26}
Radio
Single selection control for a list of options.
1import { Radio, VStack } from '@/components/ui';2import { useState } from 'react';34export default function RadioExample() {5 const [selected, setSelected] = useState('option1');67 return (8 <VStack className="gap-4">9 <Radio10 checked={selected === 'option1'}11 onChange={() => setSelected('option1')}12 label="Option 1"13 accessibilityLabel="Option 1"14 />15 <Radio16 checked={selected === 'option2'}17 onChange={() => setSelected('option2')}18 label="Option 2"19 accessibilityLabel="Option 2"20 />21 </VStack>22 );23}
Select
A dropdown-like selection component using a bottom sheet.
1import { Select } from '@/components/ui';2import { useState } from 'react';34const OPTIONS = [5 { label: 'Option 1', value: '1' },6 { label: 'Option 2', value: '2' },7 { label: 'Option 3', value: '3' },8];910export default function SelectExample() {11 const [value, setValue] = useState<string | number>();1213 return (14 <Select15 label="Choose an option"16 options={OPTIONS}17 value={value}18 onSelect={setValue}19 placeholder="Select..."20 title="Options"21 />22 );23}
Separator
Visually separates content with a line.
1import { Separator, Text, View } from '@/components/ui';23export default function SeparatorExample() {4 return (5 <View>6 <Text>Item 1</Text>7 <Separator className="my-4" />8 <Text>Item 2</Text>910 <View className="flex-row h-5 items-center mt-4">11 <Text>Link 1</Text>12 <Separator orientation="vertical" className="mx-4" />13 <Text>Link 2</Text>14 </View>15 </View>16 );17}
Stacks
Layout primitives for arranging components horizontally or vertically.
1import { HStack, VStack, Center, Circle, Text } from '@/components/ui';23export default function StacksExample() {4 return (5 <VStack className="gap-4">6 <HStack className="gap-2 bg-neutral-100 p-4">7 <Text>Horizontal</Text>8 <Text>Stack</Text>9 </HStack>1011 <Center className="bg-neutral-200 p-8">12 <Text>Centered Content</Text>13 </Center>1415 <Circle className="size-20 bg-blue-500">16 <Text className="text-white">Circle</Text>17 </Circle>18 </VStack>19 );20}
Switch
A control that allows the user to toggle between on and off states.
1import { Switch } from '@/components/ui';2import { useState } from 'react';34export default function SwitchExample() {5 const [enabled, setEnabled] = useState(false);67 return (8 <Switch9 checked={enabled}10 onChange={setEnabled}11 label="Enable notifications"12 accessibilityLabel="Notifications switch"13 />14 );15}
Text
Typography component that handles fonts, sizes, and localization.
1import { Text, VStack } from '@/components/ui';23export default function TextExample() {4 return (5 <VStack className="gap-2">6 <Text className="text-4xl font-bold">Heading 1</Text>7 <Text className="text-2xl font-semibold">Heading 2</Text>8 <Text className="text-base text-neutral-500">Body text with regular font.</Text>910 {/* With i18n key */}11 {/* <Text tx="welcome.message" /> */}12 </VStack>13 );14}
View
An enhanced View component with animation capabilities using Moti.
1import { View, Text, Button } from '@/components/ui';2import { useState } from 'react';34export default function ViewExample() {5 const [isVisible, setIsVisible] = useState(true);67 return (8 <>9 <Button onPress={() => setIsVisible(!isVisible)} label="Toggle View" />1011 <View12 animatePresence13 isVisible={isVisible}14 motionPreset="fadeUp"15 className="p-4 bg-neutral-100 rounded-xl mt-4"16 >17 <Text>I animate in and out!</Text>18 </View>19 </>20 );21}
Last updated on 2/10/2026
Edit this page on GitHub