Install
openclaw skills install expo-native-uiBuild beautiful native iOS/Android apps with Expo Router. Covers route structure, native tabs, animations, blur effects, liquid glass, SF Symbols, and platform patterns.
openclaw skills install expo-native-uiBuild production-quality native mobile apps with Expo Router following Apple Human Interface Guidelines and modern React Native patterns.
npx clawhub@latest install expo-native-ui
Guides implementation of native mobile apps using Expo Router with:
expo router, react native, native tabs, sf symbols, expo blur, liquid glass, reanimated, ios, android, mobile app, navigation stack, form sheet, modal, context menu, link preview
Consult these resources for detailed implementation:
| Reference | Purpose |
|---|---|
references/route-structure.md | Route conventions, dynamic routes, groups, query params |
references/tabs.md | NativeTabs, migration from JS tabs, iOS 26 features |
references/icons.md | SF Symbols with expo-symbols, animations, weights |
references/controls.md | Native iOS controls: Switch, Slider, DateTimePicker, Picker |
references/visual-effects.md | Blur effects and liquid glass |
references/animations.md | Reanimated: entering, exiting, layout, scroll-driven |
references/search.md | Search bar integration, useSearch hook, filtering |
references/gradients.md | CSS gradients via experimental_backgroundImage |
references/media.md | Camera, audio, video, file saving |
references/storage.md | SQLite, AsyncStorage, SecureStore |
references/webgpu-three.md | WebGPU, Three.js for 3D graphics |
references/toolbar-and-headers.md | Stack headers, toolbar customization (iOS) |
Try Expo Go first before creating custom builds:
npx expo start # Scan QR with Expo Go
Custom builds (npx expo run:ios) only needed for:
modules/)@bacons/apple-targets)comment-card.tsxapp/ directory| Use | Instead Of |
|---|---|
expo-audio | expo-av |
expo-video | expo-av |
expo-symbols | @expo/vector-icons |
react-native-safe-area-context | RN SafeAreaView |
process.env.EXPO_OS | Platform.OS |
React.use | React.useContext |
expo-image | intrinsic img element |
expo-glass-effect | custom blur views |
// Always wrap root in ScrollView with automatic insets
<ScrollView contentInsetAdjustmentBehavior="automatic">
{children}
</ScrollView>
// Use useWindowDimensions, not Dimensions.get()
const { width, height } = useWindowDimensions();
// Flexbox over Dimensions API
<View style={{ flex: 1, flexDirection: 'row', gap: 16 }} />
import { Link } from 'expo-router';
<Link href="/settings">
<Link.Trigger>
<Pressable><Card /></Pressable>
</Link.Trigger>
<Link.Preview />
<Link.Menu>
<Link.MenuAction title="Share" icon="square.and.arrow.up" onPress={handleShare} />
<Link.MenuAction title="Delete" icon="trash" destructive onPress={handleDelete} />
</Link.Menu>
</Link>
// In _layout.tsx
<Stack.Screen
name="sheet"
options={{
presentation: "formSheet",
sheetGrabberVisible: true,
sheetAllowedDetents: [0.5, 1.0],
contentStyle: { backgroundColor: "transparent" }, // Liquid glass on iOS 26+
}}
/>
app/
_layout.tsx — <NativeTabs />
(index,search)/
_layout.tsx — <Stack />
index.tsx
search.tsx
// app/_layout.tsx
import { NativeTabs, Icon, Label } from "expo-router/unstable-native-tabs";
export default function Layout() {
return (
<NativeTabs>
<NativeTabs.Trigger name="(index)">
<Icon sf="list.dash" />
<Label>Items</Label>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="(search)" role="search" />
</NativeTabs>
);
}
borderCurve: 'continuous' for rounded corners (not capsules)boxShadow style prop, never legacy RN shadow/elevationStyleSheet.create unless reusingfontVariant: 'tabular-nums' for numeric countersselectable prop on Text displaying copiable data// Shadow example
<View style={{ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)" }} />
// Continuous border curve
<View style={{ borderRadius: 12, borderCurve: 'continuous' }} />
expo-haptics conditionally on iOSheaderSearchBarOptions in Stack.Screenselectable prop to important dataimg, div) outside DOM componentsDimensions.get() — always useWindowDimensionsapp/ directoryPlatform.OS — use process.env.EXPO_OSboxShadow@expo/vector-icons — use expo-symbols