| name | react-native-unistyles-v3 |
| description | Guide for using react-native-unistyles v3. Triggers on: "unistyles", "StyleSheet.create", "create stylesheet", "add theme", "breakpoints", "variants", "withUnistyles", "useUnistyles", "ScopedTheme", "UnistylesRuntime", "style component", "responsive styles", "media queries", "dynamic styles", "scoped theme", "adaptive theme", "unistyles setup", "unistyles config". Covers setup, theming, responsive design, variants, web features, third-party integration, and troubleshooting.
|
| disable-model-invocation | false |
| user-invocable | true |
| allowed-tools | Read, Grep, Glob, Edit, Write, Bash(npx *) |
React Native Unistyles v3 Skill
You are assisting with React Native Unistyles v3 styling. v3 is a zero-re-render styling library with a C++ core (Nitro Modules) and Babel plugin that processes StyleSheets at build time. It replaces React Native's StyleSheet with a reactive, theme-aware, responsive system.
Prerequisites
- React Native 0.78+ with New Architecture mandatory (default from RN 0.83+)
- React 19+ (enforced at runtime)
react-native-nitro-modules (native bridge dependency)
react-native-edge-to-edge (required for Android edge-to-edge insets)
- Expo SDK 53+ (if using Expo; not compatible with Expo Go ā requires dev client or prebuild)
- Xcode 16+ (iOS)
Workflow
- Read user's code first ā understand current setup, imports, and styling approach
- Identify intent ā new setup, add theming, responsive design, fix an issue, etc.
- Apply v3 patterns ā use the correct API from this skill; consult reference files for details
- Verify correctness ā check for critical rule violations (spreading, barrel re-exports, etc.)
Quick Reference
StyleSheet.create ā 3 overloads
import { StyleSheet } from 'react-native-unistyles'
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 }
})
const styles = StyleSheet.create(theme => ({
container: { backgroundColor: theme.colors.background }
}))
const styles = StyleSheet.create((theme, rt) => ({
container: {
backgroundColor: theme.colors.background,
paddingTop: rt.insets.top,
width: rt.screen.width > 768 ? 500 : rt.screen.width - 32
}
}))
StyleSheet.configure ā one-time setup
StyleSheet.configure({
themes: { light: lightTheme, dark: darkTheme },
breakpoints: { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200 },
settings: {
initialTheme: 'light',
}
})
Variants
const styles = StyleSheet.create(theme => ({
button: {
variants: {
size: {
small: { padding: 4 },
medium: { padding: 8 },
large: { padding: 16 },
},
color: {
primary: { backgroundColor: theme.colors.primary },
secondary: { backgroundColor: theme.colors.secondary },
}
},
compoundVariants: [
{ size: 'large', color: 'primary', styles: { borderWidth: 2 } }
],
}
}))
styles.useVariants({ size: 'large', color: 'primary' })
return <View style={styles.button} />
withUnistyles ā wrap third-party components (not React Native or Reanimated components)
import { withUnistyles } from 'react-native-unistyles'
import { Button } from 'some-library'
const UniButton = withUnistyles(Button, (theme, rt) => ({
color: theme.colors.primary,
size: rt.screen.width > 400 ? 'large' : 'small'
}))
Critical Rules
- NEVER spread styles ā
{...styles.x} breaks C++ proxy binding. ALWAYS use array syntax: [styles.x, styles.y] or [styles.x, { marginTop: 10 }]
- NEVER re-export StyleSheet from barrel files ā the Babel plugin detects
StyleSheet.create by import source. Re-exporting breaks detection.
- Babel plugin is REQUIRED ā add
['react-native-unistyles/plugin', { root: 'src' }] to babel.config.js. Without it, styles won't be reactive.
- Import StyleSheet from
react-native-unistyles only ā it polyfills all RN StyleSheet APIs (hairlineWidth, compose, flatten, absoluteFill). Replace all import { StyleSheet } from 'react-native'.
styles.useVariants() must be called before accessing variant-dependent styles ā treat it like a React hook (top of component).
- Prefer
StyleSheet.create(theme => ...) over useUnistyles() ā theme functions cause zero re-renders; useUnistyles() re-renders on every theme/runtime change.
StyleSheet.configure() must be called before any StyleSheet.create() ā typically in your app entry point, before any component renders.
Decision Trees
Choosing a styling approach
Need theme/runtime in styles?
āā YES ā StyleSheet.create((theme, rt) => ...) [zero re-renders]
āā NO ā StyleSheet.create({ ... }) [static styles]
Need theme values as non-style props?
āā YES ā withUnistyles(Component, (theme, rt) => ({ propName: theme.value }))
āā NO ā Pass Unistyles styles via style prop directly
Need theme/runtime in component logic (not just styles)?
āā YES ā useUnistyles() hook [causes re-renders]
āā NO ā Use StyleSheet.create with theme function
Third-party component integration
Does the component accept a `style` prop?
āā YES ā Pass Unistyles styles directly (Babel auto-processes standard RN views)
ā If it's a custom native view ā add to autoProcessPaths in Babel config
āā NO ā Does it accept theme-derived props (color, size, etc.)?
ā āā YES ā withUnistyles(Component, (theme, rt) => ({ prop: theme.value }))
ā āā NO ā useUnistyles() as fallback
āā Component from node_modules not processed?
ā Add its path to autoProcessPaths or autoProcessImports in Babel plugin config
Reference Files
- Setup, installation, Babel plugin, TypeScript, testing, Expo Router: read references/setup-guide.md
- Complete API for every export: read references/api-reference.md
- Code patterns: themes, variants, breakpoints, web, SSR, Reanimated: read references/styling-patterns.md
- withUnistyles, autoProcessPaths, React Compiler, Reanimated, FlatList: read references/third-party-integration.md
- Troubleshooting from 150+ GitHub issues with solutions: read references/common-issues.md