- Accordion
- Action Sheet
- Alert Dialog
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- AvoidKeyboard
- Badge
- BottomSheet
- Button
- Camera Preview
- Camera
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input OTP
- Input
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Use this when you already have an Expo project. Do not run npx bna-ui init
over it — that scaffolds a whole app and will overwrite what you have.
There are two ways in. The CLI can install everything for you, or you can copy the files by hand.
Add the @/* alias to your tsconfig.json
Every file BNA UI installs imports through @/…, so this has to exist first:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"paths": {
"@/*": ["./*"]
}
},
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}This is also what tells the CLI where files go. If your app lives under src/,
map the alias there — "@/*": ["./src/*"] — and add installs into
src/components/ui/… to match.
Add any component
pnpm dlx bna-ui add button
The theme files and hooks it depends on come along automatically, as do its npm dependencies. Run it with no arguments to browse everything:
pnpm dlx bna-ui add
Wrap your root layout
See wire it up below.
Wire it up
Wrap your root layout in ThemeProvider so components can resolve colours:
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { ThemeProvider } from '@/providers/theme-provider';
export default function RootLayout() {
return (
<ThemeProvider>
<Stack>
<Stack.Screen name='(tabs)' options={{ headerShown: false }} />
<Stack.Screen name='+not-found' />
</Stack>
<StatusBar style='auto' />
</ThemeProvider>
);
}Using it
Components read colours through useColor, so light and dark work with no
per-component wiring:
import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { useColor } from '@/hooks/useColor';
export default function Screen() {
const background = useColor('background');
return (
<View style={{ flex: 1, padding: 24, backgroundColor: background }}>
<Text variant='heading'>Hello</Text>
<Button onPress={() => {}}>Get started</Button>
</View>
);
}Next
- Browse the components
- Theming — how the tokens fit together
- CLI reference