A native app is configured through one provider, ThemeProvider. It takes the style options of the web ThemeProvider, with the same names and the same defaults, and resolves them against the same design tokens. A native screen and a web page with the same options get the same colours, spacing, radii and type. For the web setup, see the web configuration and the web ThemeProvider.
Wrap the app once, at the root:
Every prop is optional. Without any, you get the web defaults below, following the device's light or dark setting.
When mobileSize, tabletSize and desktopSize are left out, rem comes from the tokens: 15 points on phones and 16 on tablets, as on the web.
Pass the family names the app registered, for example with expo-font:
The quick start covers loading fonts step by step.
ThemeProvider is controlled by its props. It does not store a choice or offer a setTheme. To let people pick light or dark, keep the choice in your own state (and storage, if it should survive a restart) and pass it in:
useTheme() returns the resolved theme, so your own components can use the same tokens as Once UI's. Outside a ThemeProvider it returns the web defaults in dark.
The theme follows the window width, so it changes when the device rotates or an iPad app is resized.
createTheme builds the same object without a provider, for code that runs outside React or for tests. It takes full settings, a width in points, and optionally fonts and insets. defaultSettings holds the web defaults:
tokens is the token export both packages read: the web package's SCSS tokens as JSON, in layers that each apply to a set of options and a width. resolveTokens(settings, width) applies the layers in CSS cascade order and follows references, so it returns what the browser would compute for each custom property.
The same file ships as @once-ui-system/native/tokens.json and @once-ui-system/core/tokens.json, for other tools such as Figma or Swift and Kotlin code generators.
Icon, IconButton and the prefixIcon and suffixIcon props draw the web package's built-in icons. IconProvider adds icons of your own, or replaces built-in ones, by name. An icon is either core's SVG data ({ tag, attr, child }) or a component that takes size and color, such as one from @expo/vector-icons.
Declaring the name in IconLibraryOverrides makes it valid wherever an icon name is typed. Put IconProvider inside ThemeProvider, around the screens that use the icons.
- No config file. There is no defineConfig, ThemeInit or LayoutProvider. Pass the options to ThemeProvider directly, or spread an object of them.
- No stored theme. The web ThemeProvider saves the choice in localStorage and its useTheme has setTheme. On native the app keeps the choice and passes theme.
- useTheme returns tokens. It returns the resolved theme described above, not the web hook's theme state.
- Not supported: transition, the custom colour seeds (brandSeed, accentSeed, neutralSeed) and the "custom" scheme, cursorInteractive, and DataThemeProvider, as there are no charts.
- Translucent surfaces use the alpha colours without a backdrop blur.
- Fonts are family names the app has loaded, not next/font results.
- Safe areas come from insets instead of CSS env().