@once-ui-system/native brings Once UI's basic components to iOS and Android apps built with React Native. They take the same props as the web components and read the same design tokens, so a screen written with Once UI looks and reads the same on a phone.
It is a preview. Most apps should keep shipping Once UI on phones as the web build wrapped in a native shell (the Stack mobile target); use this package when the app itself has to be native.
Needs React 19, React Native 0.79 or later (Expo SDK 53 and up) and react-native-svg 15, which Expo includes. Preview versions are published to the next tag.
Wrap the app in ThemeProvider. It takes the same style options as on the web, with the same defaults; theme="system" follows the device.
IconProvider adds icons of your own, by name: core's SVG data, or a component that takes size and color, such as one from @expo/vector-icons.
useTheme() gives your own components the resolved tokens: theme.color("brand-solid-strong"), theme.space("16"), theme.radius("l"), theme.text("heading-strong-m"), theme.shadow("m").
Flex, Row, Column and Card take the same breakpoint props as on the web: xl, l, m, s and xs. Each one applies on screens up to its width (480, 768, 1024 and 1440 points; xl on every screen), and a smaller breakpoint wins over a larger one, as in the browser.
They take layout, spacing, sizes, position and offsets, colours, borders, radius, shadow, opacity, zIndex, hide and style. Text styles, solid, single-side borders, transitions and scrollbars have no native equivalent and are not supported. position can be relative, absolute or static: React Native has no fixed or sticky positioning.
Phones keep parts of the screen for the notch, the status bar and the home indicator. React Native has no built-in way to read them on every platform, so pass them to ThemeProvider, for example from react-native-safe-area-context (included in Expo):
With the insets in place, Dialog sheets clear the home indicator and toasts appear above it. Add safeArea to a Flex, Row or Column to pad it by the safe areas: safeArea for every edge, or a list such as safeArea={["top", "bottom"]}. useTheme().insets gives them to your own components.
- Units. Numbers on spacing and size props are rem, as on the web. Rem follows the screen size: 15pt on phones, 16pt on tablets.
- Touch. Pressed states replace hover, and small controls take taps from at least 44pt around them without being drawn larger.
- Clipping. radius does not clip children. Pass overflow="hidden" when it should; on iOS that also hides the view's shadow.
- Media shows images only. Enlarging on tap, videos and YouTube embeds are not supported.
- Tabs have no arrow-key navigation, so activation has no effect.
- Core 3.0 names. Accordion also takes defaultOpen and onOpenChange, Tabs takes onValueChange, and StatusIndicator takes scheme, so code written for 3.0 works here too.
- Safe areas. The app passes the screen's safe areas to ThemeProvider, as shown below, instead of the browser providing them.
Both packages read one token export generated from the web package's SCSS tokens, so a token change reaches the web and native apps together. The same file ships as @once-ui-system/core/tokens.json for other tools, such as Figma or Swift and Kotlin code generators.