TrademarkTrademark
Docs
Ctrl k
Search docs...
React Native

Configuration

Updated: October 18, 2026
View on GitHub
Soon
Not released yet. This is on main and is not in any published version yet. It will not install today.

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.

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.

Props

Prop
Type
Default
Description
theme"light" | "dark" | "system""system""system" follows the device's appearance and updates when it changes.
brandSchemes"blue"The brand colour scheme: blue, indigo, violet, magenta, pink, red, orange, yellow, moss, green, emerald, aqua or cyan.
accentSchemes"indigo"The accent colour scheme. Same values as brand.
neutral"sand" | "gray" | "slate" | "rose" | "mint" | "dusk""gray"The neutral scheme for text, borders and surfaces.
solid"color" | "contrast" | "inverse""contrast"How solid fills, such as the primary Button, are coloured.
solidStyle"flat" | "plastic""flat"Flat fills, or fills with a highlight and a shade.
border"rounded" | "playful" | "conservative" | "sharp""playful"The radius scale.
surface"filled" | "translucent""filled"Opaque surfaces, or surfaces in the alpha colours.
scaling"90" | "95" | "100" | "105" | "110""100"Scales spacing, sizes and type, in percent.
bodySize"90" | "95" | "100" | "105" | "110""100"Scales the body text sizes, in percent.
bodyLineHeight"90" | "100" | "110" | "120""100"Scales the body line heights, in percent.
mobileSize"13" to "18"-Points per rem on screens 768 points wide and narrower.
tabletSize"13" to "18"-Points per rem on screens from 769 to 1024 points wide.
desktopSize"13" to "18"-Points per rem on screens wider than 1024 points.
fontsFontFamilies-{ heading, body, label, code }: font families the app has loaded. Any left out use the platform font. heading also covers the display variants.
insetsInsetsall 0{ top, right, bottom, left } safe-area insets in points, as useSafeAreaInsets() returns them. Used by Dialog, toasts and safeArea.
childrenReactNode-The app.

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.

Fonts

Pass the family names the app registered, for example with expo-font:

The quick start covers loading fonts step by step.

Switching the theme at runtime

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

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.

Field
Type
Description
settingsStyleSettingsThe options in force, with theme resolved to "light" or "dark".
widthnumberThe window width in points the theme was resolved for.
breakpointsBreakpointsMax-width of each breakpoint: xs 480, s 768, m 1024, l 1440, xl Infinity.
insetsInsetsThe safe-area insets passed to ThemeProvider, or zeros.
remnumberPoints per rem on this screen.
tokensRecord<string, TokenValue>Every resolved token, by its CSS name without --, such as "brand-solid-strong".
px(name)(name: string) => numberA length token in points, such as "radius-l-nest-4".
color(name)(name: string) => stringA colour token as a hex string, such as "neutral-alpha-weak" or "page-background". "transparent" for an unknown name.
background(value)(value) => stringA background prop value ("neutral-medium", "surface", "page", "overlay") as a colour.
border(value)(value) => stringA border prop value ("neutral-alpha-weak", "surface") as a colour.
onBackground(value)(value) => stringText colour for an onBackground value, such as "neutral-weak".
onSolid(value)(value) => stringText colour for an onSolid value, such as "brand-strong".
space(value)(value: SpacingToken | number) => numberA spacing token ("16", "l") or a number of rem, in points.
radius(size)(size: RadiusSize) => numberA radius in points. "full" is 9999, "none" is 0.
shadow(size)(size: ShadowSize) => ViewStyleA shadow style: boxShadow with every layer, plus shadow* and elevation fallbacks.
text(variant)(variant: TextVariant) => TextStylefontSize, lineHeight, fontWeight, the family from fonts, and letter spacing for display sizes.

The theme follows the window width, so it changes when the device rotates or an iPad app is resized.

createTheme

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

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.

IconProvider

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.

Differences from the web

  • 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().
Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club