One ships @vxrn/native — a package of native navigation primitives that bring iOS and Android platform features to your app. These are experimental and the API may change.
npm install @vxrn/native@vxrn/native uses standard React Native native modules (RCTViewManager + TurboModules) and links automatically during the native build.
Type-safe platform colors for iOS and Android. Works with PlatformColor under the hood.
import { Color } from '@vxrn/native'
// iOS system colors<View style={{ backgroundColor: Color.ios.systemBlue }} /><Text style={{ color: Color.ios.label }} />
// Android Material Design 3<View style={{ backgroundColor: Color.android.dynamic.primary }} /><View style={{ backgroundColor: Color.android.material.surface }} />All UIKit semantic colors: systemBlue, systemRed, systemGreen, label, secondaryLabel, systemBackground, separator, systemFill, systemGray through systemGray6, and more.
Color.android.black, Color.android.white — system colors via PlatformColorColor.android.material.primary — static Material Design 3 baseline colorsColor.android.dynamic.primary — dynamic colors that adapt to the user’s wallpaper (Android 12+)Native iOS 18+ zoom transitions. The destination screen expands from a source element with a fluid animation.
import { ZoomTransitionSource, ZoomTransitionEnabler } from '@vxrn/native'
// source screen — wrap the tappable elementfunction ListScreen() { const router = useRouter() return ( <ZoomTransitionSource identifier="item-1"> <Pressable onPress={() => router.push('/detail?id=item-1')}> <Text>Mountain View</Text> </Pressable> </ZoomTransitionSource> )}
// destination screen — place the enabler anywherefunction DetailScreen() { const { id } = useParams() return ( <View> <Stack.Screen options={{ headerShown: false }} /> <ZoomTransitionEnabler zoomTransitionSourceIdentifier={id} /> <Text>Detail for {id}</Text> </View> )}headerShown: false on the detail screen to avoid the header overlapping during the zoom animationidentifier must match between ZoomTransitionSource and ZoomTransitionEnablerZoomTransitionAlignmentRectDetector on the destination to align the zoom to a specific elementNative iOS UIToolbar rendered at the bottom of the screen. Supports SF Symbols, badges, and Liquid Glass on iOS 26.
For routed screens, prefer Stack.Toolbar. It is exported by one and adds header and bottom toolbars with buttons, menus, spacers, custom views, and search-bar placement. You must install @vxrn/native directly in the app and add import '@vxrn/native' to its native setup file. The package supplies the native implementation and declares its native dependencies. The primitives below are its lower-level building blocks.
import { ToolbarHost, ToolbarItem, Color } from '@vxrn/native'
function MyScreen() { return ( <View style={{ flex: 1 }}> <Text>Content</Text>
<ToolbarHost> <ToolbarItem identifier="add" title="Add" systemImageName="plus" tintColor={Color.ios.systemBlue} onSelected={() => console.log('add tapped')} /> <ToolbarItem identifier="spacer" type="fluidSpacer" /> <ToolbarItem identifier="share" title="Share" systemImageName="square.and.arrow.up" barButtonItemStyle="prominent" onSelected={() => console.log('share tapped')} /> <ToolbarItem identifier="settings" systemImageName="gearshape" badgeConfiguration={{ value: '3' }} onSelected={() => console.log('settings tapped')} /> </ToolbarHost> </View> )}| Prop | Type | Description |
|---|---|---|
identifier | string | Unique ID (required) |
title | string | Button title |
systemImageName | string | SF Symbol name |
type | 'normal' | 'fixedSpacer' | 'fluidSpacer' | 'searchBar' | Item type |
barButtonItemStyle | 'plain' | 'prominent' | Button style |
badgeConfiguration | { value?: string } | Badge (iOS 26+) |
disabled | boolean | Disable the button |
hidden | boolean | Hide the button |
onSelected | () => void | Tap handler |
Native iOS UIMenu and UIAction for context menus in toolbars.
import { MenuAction } from '@vxrn/native'
<MenuAction identifier="edit" title="Edit" icon="pencil" onSelected={() => console.log('edit')}/>
<MenuAction identifier="delete" title="Delete" icon="trash" destructive onSelected={() => console.log('delete')}/>Native UISplitViewController for iPad multi-column layouts.
react-native-screens gamma mode. Add this to the top of your Podfile:ENV['RNS_GAMMA_ENABLED'] ||= '1'pod install. Currently blocked on a react-native-screens upstream issue with Fabric — tracking for a fix.import { SplitView } from '@vxrn/native'
function Layout() { return ( <SplitView> <SplitView.Column> <SidebarContent /> </SplitView.Column> </SplitView> )}On iPhone, SplitView collapses to a single column automatically.
Platform-native tab bars using react-native-bottom-tabs. Renders UITabBarController on iOS and BottomNavigationView on Android.
npx expo install @bottom-tabs/react-navigation react-native-bottom-tabsimport { NativeTabs } from 'one/native-tabs'
export default function Layout() { return ( <NativeTabs> <NativeTabs.Screen name="feed" options={{ title: 'Feed', tabBarIcon: () => ({ sfSymbol: 'newspaper' }), }} /> <NativeTabs.Screen name="profile" options={{ title: 'Profile', tabBarIcon: () => ({ sfSymbol: 'person' }), }} /> </NativeTabs> )}Guard routes behind authentication:
<NativeTabs> <NativeTabs.Screen name="login" /> <NativeTabs.Protected guard={isAuthed}> <NativeTabs.Screen name="dashboard" /> <NativeTabs.Screen name="settings" /> </NativeTabs.Protected></NativeTabs>| Feature | iOS | Android | Web |
|---|---|---|---|
| Color API | system colors via PlatformColor | Material 3 dynamic/static | returns null |
| Zoom Transitions | iOS 18+ | — | — |
| Toolbar | UIToolbar + SF Symbols | — | — |
| Menu Actions | UIMenu / UIAction | — | — |
| SplitView | iPad (gamma required) | — | — |
| NativeTabs | UITabBarController | BottomNavigationView | — |
All components return null on unsupported platforms — safe to use in cross-platform code.
Edit this page on GitHub.