Skip to main content

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.js and .bo$$/native.d.ts generated next to the web runtime.
  • $$ defaults to View (not div).
  • $$.Text, $$.Image, etc map to React Native components.
  • Tokens resolve to literal values at runtime (no CSS variables).

Setup

  1. Ensure react-native is installed in the project (Boss reads RN types to build the prop list).

  2. 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,
],
}
  1. 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:

  1. Add the native plugin to .bo$$/config.js (same as above).
  2. 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)
  • Text
  • Image
  • ScrollView
  • Pressable
  • TextInput
  • SafeAreaView
  • Modal
  • FlatList
  • SectionList
  • Switch
  • TouchableOpacity
  • TouchableHighlight
  • TouchableWithoutFeedback
  • ActivityIndicator

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 into style.
  • Non-style props: passed through to the native component.

Boss merges style props with existing style values:

  • If style is an object, it merges objects.
  • If style is 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.ts includes React Native style prop types.
  • Autocomplete appears as soon as you import ./.bo$$/native anywhere 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:

  • className
  • child (arbitrary selectors)
  • pseudo nesting
  • at queries

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-native so Boss can read its type definitions.

No native.js output

  • Ensure boss-css/native/server is included in the plugin list.
  • Ensure the config is being loaded from the correct .bo$$ folder.