Shipnative uses Unistyles 3.0 for styling. Theme support and dark mode work automatically.
Quick Reference
The Pattern
import { StyleSheet, useUnistyles } from 'react-native-unistyles'
function MyComponent() {
const { theme } = useUnistyles()
return (
<View style={styles.container}>
<Text style={styles.title}>Hello!</Text>
</View>
)
}
const styles = StyleSheet.create((theme) => ({
container: {
flex: 1,
backgroundColor: theme.colors.background,
padding: theme.spacing.md,
},
title: {
fontSize: theme.typography.sizes['2xl'],
fontFamily: theme.typography.fonts.bold,
color: theme.colors.foreground,
},
}))
Common Theme Values
| Category | Values |
|---|
| Colors | theme.colors.primary, background, foreground, card, error, muted |
| Neutral Palette | theme.colors.neutral100 through neutral900 (Modern Slate palette) |
| Spacing | theme.spacing.xs (4), sm (8), md (16), lg (24), xl (32) |
| Typography | theme.typography.sizes.base, lg, xl, 2xl |
| Fonts | theme.typography.fonts.regular, medium, bold |
| Radius | theme.radius.sm, md, lg, full |
| Shadows | theme.shadows.sm, md, lg |
Full theme definition: apps/app/app/theme/unistyles.ts
Key Rules
Never hardcode values. Always use theme tokens.
// DON'T
const styles = StyleSheet.create({
container: {
backgroundColor: '#ffffff',
padding: 16,
color: '#000000',
}
})
// DO
const styles = StyleSheet.create((theme) => ({
container: {
backgroundColor: theme.colors.background,
padding: theme.spacing.md,
color: theme.colors.foreground,
}
}))
This ensures:
- Dark mode works automatically
- Consistent design across your app
- Easy theme customization later
Dark Mode
It’s automatic! Semantic color names switch between light and dark:
// Works in both light and dark mode
const styles = StyleSheet.create((theme) => ({
container: {
backgroundColor: theme.colors.background, // white in light, dark gray in dark
},
text: {
color: theme.colors.foreground, // black in light, white in dark
},
}))
No conditional logic needed. Just use theme colors and it works.
Detecting Dark Mode
import { UnistylesRuntime } from 'react-native-unistyles'
// Check current theme
const isDark = UnistylesRuntime.themeName === "dark"
// Change theme programmatically
UnistylesRuntime.setTheme("dark")
UnistylesRuntime.setTheme("light")
// Follow system theme
UnistylesRuntime.setAdaptiveThemes(true)
Migration Note: The old useAppTheme() hook has been removed. Always use useUnistyles() and UnistylesRuntime for theme access and switching.
Component Showcase
Shipnative includes a visual gallery of all components. Open it via:
- iOS Simulator:
Cmd + D → Component Showcase
- Android Emulator:
Cmd + M → Component Showcase
- Physical Device: Shake → Component Showcase
You’ll see every component with:
- All variants and sizes
- Light and dark mode versions
- Copy-paste code snippets
Built-in Components
These are ready to use from @/components:
| Component | Props |
|---|
| Button | variant: filled, outlined, ghost, danger |
| TextField | label, error, helper, secureTextEntry |
| Card | preset: default, elevated, outlined |
| Text | preset: heading, subheading, body, caption |
| Avatar | source, initials, size |
| Badge | Status indicators |
| Spinner | Loading indicator |
| Divider | Horizontal separator |
import { Button, Card, Text, TextField } from '@/components'
<Card preset="elevated">
<Text preset="heading">Welcome</Text>
<TextField label="Email" placeholder="you@example.com" />
<Button variant="filled" onPress={handleSubmit}>
Continue
</Button>
</Card>
Variants
Unistyles lets you define style variants for different states:
import { StyleSheet, useUnistyles } from 'react-native-unistyles'
import { Pressable, Text } from 'react-native'
type ButtonVariant = 'filled' | 'outlined' | 'ghost'
type ButtonSize = 'sm' | 'md' | 'lg'
interface ButtonProps {
variant?: ButtonVariant
size?: ButtonSize
onPress: () => void
children: React.ReactNode
}
function Button({ variant = 'filled', size = 'md', onPress, children }: ButtonProps) {
return (
<Pressable
style={[
styles.base,
styles.variants({ variant, size })
]}
onPress={onPress}
>
<Text style={styles.text({ variant })}>{children}</Text>
</Pressable>
)
}
const styles = StyleSheet.create((theme) => ({
base: {
borderRadius: theme.radius.md,
justifyContent: 'center',
alignItems: 'center',
},
variants: {
variants: {
variant: {
filled: {
backgroundColor: theme.colors.primary,
},
outlined: {
borderWidth: 1,
borderColor: theme.colors.border,
backgroundColor: 'transparent',
},
ghost: {
backgroundColor: 'transparent',
},
},
size: {
sm: { height: 36, paddingHorizontal: theme.spacing.md },
md: { height: 44, paddingHorizontal: theme.spacing.lg },
lg: { height: 56, paddingHorizontal: theme.spacing.xl },
},
},
},
text: {
variants: {
variant: {
filled: { color: theme.colors.primaryForeground },
outlined: { color: theme.colors.foreground },
ghost: { color: theme.colors.primary },
},
},
},
}))
Responsive Styles
const styles = StyleSheet.create((theme, runtime) => ({
container: {
flexDirection: 'column',
padding: theme.spacing.md,
// Tablet and up
variants: {
breakpoint: {
md: {
flexDirection: 'row',
maxWidth: 800,
alignSelf: 'center',
},
},
},
},
}))
Breakpoints are defined in apps/app/app/theme/unistyles.ts.
Common Mistakes
| Mistake | Fix |
|---|
Hardcoded colors like #000000 | Use theme.colors.foreground |
Hardcoded spacing like 16 | Use theme.spacing.md |
| Inline styles everywhere | Use StyleSheet.create |
| Missing theme function | Use StyleSheet.create((theme) => ({ ... })) |
| Using NativeWind/Tailwind | NativeWind was removed, use Unistyles |
Customizing the Theme
Edit apps/app/app/theme/unistyles.ts to change:
export const lightTheme = {
colors: {
primary: '#6366F1', // Your brand color
primaryForeground: '#fff',
background: '#ffffff',
foreground: '#000000',
// ... more colors
},
spacing: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
// ... typography, radius, shadows
}
export const darkTheme = {
colors: {
primary: '#818CF8', // Slightly lighter for dark mode
primaryForeground: '#fff',
background: '#0a0a0a',
foreground: '#ffffff',
// ... matching structure
},
// Same spacing, typography, etc.
}
Resources
- Unistyles Documentation
- Theme file:
apps/app/app/theme/unistyles.ts
- Components:
apps/app/app/components/
- Component Showcase: Dev Menu in running app