React Native
Boss CSS can emit a React Native runtime alongside the existing web output. The native runtime uses the same $$ API but maps props into React Native style and passes non-style props through as native component props.
What you get
.bo$$/native.jsand.bo$$/native.d.tsgenerated next to the web runtime.$$defaults toView(notdiv).$$.Text,$$.Image, etc map to React Native components.- Tokens resolve to literal values at runtime (no CSS variables).
Setup
-
Ensure
react-nativeis installed in the project (Boss reads RN types to build the prop list). -
Add the native plugin to your
.bo$$/config.js:
import * as native from 'boss-css/native/server'
export default {
folder: './.bo$$',
plugins: [
// web plugins...
native,
],
}
- Import the native runtime in your app entry:
// App.tsx (or your RN entry)
import $$ from './.bo$$/native'
export default function App() {
return <$$ padding={12}><$$.Text>Native UI</$$.Text></$$>
}
If you want the global $$, the native plugin enables it by default. You can disable it in config:
import * as native from 'boss-css/native/server'
native.settings.set('globals', false)
Expo setup (managed workflow)
Minimal setup for Expo projects:
- Add the native plugin to
.bo$$/config.js(same as above). - Import the native runtime in your Expo entry:
// App.tsx
import $$ from './.bo$$/native'
export default function App() {
return (
<$$ padding={12}>
<$$.Text>Expo + Boss</$$.Text>
</$$>
)
}
If you want full CSS output on web (selectors, pseudos, media queries), keep the web runtime available and use a web-specific entry:
// App.web.tsx
import $$ from './.bo$$'
// App.native.tsx
import $$ from './.bo$$/native'
Using as and custom components
as works with native component references, not DOM tag strings:
import { Pressable } from 'react-native'
<$$ as={Pressable} padding={12} borderRadius={10}>
<$$.Text>Press me</$$.Text>
</$$>
Custom components also work as long as they forward style and props:
import { View } from 'react-native'
const Card = ({ style, ...props }) => <View style={style} {...props} />
<$$ as={Card} padding={16} />
Component mapping
The native runtime maps the following keys to React Native components:
View(default)TextImageScrollViewPressableTextInputSafeAreaViewModalFlatListSectionListSwitchTouchableOpacityTouchableHighlightTouchableWithoutFeedbackActivityIndicator
Example:
<$$ padding={12}>
<$$.Text fontSize={16}>Hello</$$.Text>
<$$.Image source={{ uri: 'https://example.com/img.png' }} />
</$$>
Props and style mapping
Native props are split into two buckets:
- Style props: anything that matches React Native style types (
ViewStyle,TextStyle,ImageStyle) is placed intostyle. - Non-style props: passed through to the native component.
Boss merges style props with existing style values:
- If
styleis an object, it merges objects. - If
styleis an array, it appends the Boss styles to the array.
<$$
testID="card"
style={{ opacity: 0.7 }}
margin={12}
shadowOffset={{ width: 0, height: 4 }}
/>
Resulting style:
{ opacity: 0.7, margin: 12, shadowOffset: { width: 0, height: 4 } }
Custom native style props
If you rely on additional style props, add them in config:
export default {
nativeStyleProps: ['shadowRadius', 'gap'],
}
Numeric values
String numbers are converted to numbers:
<$$ margin="12" /> // -> 12
Arrays are preserved (useful for transforms):
<$$ transform={[{ scale: 1.1 }]} />
Dynamic values
Functions are evaluated at runtime:
<$$ padding={() => 12} />
Tokens in native
Native output resolves tokens to literal values:
<$$ color="primary" />
<$$ color={$$.token.color.primary} />
Define tokens in your config:
export default {
tokens: {
color: {
primary: '#ed4b9b',
},
spacing: {
sm: 8,
md: 12,
},
},
}
Tokens are read from your config and embedded into native.d.ts for autocomplete.
TypeScript notes
native.d.tsincludes React Native style prop types.- Autocomplete appears as soon as you import
./.bo$$/nativeanywhere in the project. - The token type surface is embedded into the generated typings.
Unsupported features (native)
React Native does not support CSS selectors or classnames. The native runtime ignores:
classNamechild(arbitrary selectors)pseudonestingatqueries
Keep those in the web pipeline only.
Expo web
Expo renders React Native components on web. You can still use the native runtime in Expo, and the web runtime stays available for full CSS output when needed.
Troubleshooting
"native: react-native is not installed in this project"
- Install
react-nativeso Boss can read its type definitions.
No native.js output
- Ensure
boss-css/native/serveris included in the plugin list. - Ensure the config is being loaded from the correct
.bo$$folder.