TrademarkTrademark
Docs
Ctrl k
Search docs...
Native

React Native

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.

@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.

A loyalty-card screen built with @once-ui-system/native

Install

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.

Usage

Wrap the app in ThemeProvider. It takes the same style options as on the web, with the same defaults; theme="system" follows the device.

Components

Component
Notes
Flex, Row, ColumnSpacing, alignment, background, border, radius, shadow, sizes, position, hide, responsive props and safeArea. Flex is a row, as on the web.
Text, Headingvariant, onBackground, onSolid, truncate.
ButtonAll ten variants, five sizes, loading, disabled, fillWidth.
CardPressable with onPress (or onClick), selected.
Input, TextareaFloating label, error message, description, prefix and suffix, character count.
Switch, CheckboxControlled or not, with a label and description.
Icon, IconButtonThe same built-in icons as the web. prefixIcon and suffixIcon on Button and Tag take an icon name, as on the web.
DialogOpens as a bottom sheet. The back button and a tap outside close it.
ToastProvider, useToastaddToast({ variant, message }), as on the web. Toasts stack at the bottom of the screen.
SelectOpens its options in a bottom sheet, with multiple and searchable.
RadioGroup, SegmentedControlOne choice out of several, as on the web.
Chip, Badge, ProgressBarAs on the web.
Tag, Avatar, Feedback, Line, Spinner, SkeletonAs on the web.
MediaShows an image at the shape you give it, such as aspectRatio="16 / 9", with a loading placeholder until it arrives. Takes radius, border, a caption and onPress.
List, ListItemA bulleted list, or a numbered one with as="ol".
Tabs, TabList, Tab, TabPanelSwitch between panels of content, as on the web. The first tab is selected unless you pick one.
ToggleButtonA quiet button that stays highlighted while selected.
AccordionA header that opens and closes the content under it, with a short animation.
AvatarGroup, StatusIndicatorAs on the web.

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").

Responsive props

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.

Safe areas

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.

Differences from the web

  • 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.

Design tokens

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.

Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club