expo-ui

Build native iOS and Android UI with @expo/ui universal and platform-specific components.

Updated Sep 11, 2026
One-click install
npx skills add https://github.com/CYRUS-pinto/pi-bot --skill expo-ui-cyrus-pinto
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: expo-ui
Source: https://github.com/CYRUS-pinto/pi-bot/tree/main/.agents/skills/expo-ui
Command: npx skills add https://github.com/CYRUS-pinto/pi-bot --skill expo-ui-cyrus-pinto

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes scripts (resource) and references (resource) components.

What problem does it solve? Choosing the right UI approach in an Expo app is confusing: developers often reach for Reanimated, @gorhom/bottom-sheet, or React Native built-ins when @expo/ui already provides real native SwiftUI and Jetpack Compose components. This Skill guides you to the correct @expo/ui layer and prevents common mistakes like using the wrong BottomSheet props or placing platform-specific files inside Expo Router routes. ## Core Features & Use Cases - Universal components first: Use Host, Column, Row, Button, Text, List, BottomSheet, Switch, Slider, Picker, Menu, and FieldGroup from a single cross-platform API (SDK 56+). - Drop-in replacements: Migrate off community libraries like @gorhom/bottom-sheet, @react-native-community/datetimepicker, and @react-native-picker/picker via API-compatible @expo/ui/community imports. - Platform-specific layers: Build SwiftUI trees on iOS and Jetpack Compose trees on Android when universal components are insufficient, with correct .ios.tsx/.android.tsx file placement. - Component discovery script: Run list-components.js against a project's node_modules to enumerate the exact components and modifiers available in the installed @expo/ui version. - Use Case: You need a slide-up detail sheet for a map screen. Instead of installing @gorhom/bottom-sheet, use the universal BottomSheet with isPresented/onDismiss and snapPoints, wrapped in Host. ## Quick Start Ask the AI to build a settings screen or bottom sheet using @expo/ui universal components instead of React Native built-ins or community libraries.

Frequently Asked Questions about expo-ui

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I build a bottom sheet in Expo without @gorhom/bottom-sheet?

Use the universal BottomSheet from @expo/ui, controlled with isPresented and onDismiss props, wrapped in a Host component. The snapPoints prop accepts 'half', 'full', { fraction }, or { height }, and auto-sizes to content when omitted.

What is the difference between @expo/ui universal components and swift-ui or jetpack-compose imports?

Universal components from the @expo/ui root run on iOS, Android, and web from one tree. The @expo/ui/swift-ui and @expo/ui/jetpack-compose imports are platform-only layers used when universal components lack a needed component or modifier, requiring .ios.tsx/.android.tsx file splits.

Can I use @expo/ui List for large scrollable lists?

No. @expo/ui List renders native grouped rows like an iOS Settings screen and is not virtualized; each ListItem is a node on the JS thread. For large or unknown-length datasets such as feeds or search results, use FlatList or FlashList instead.

Why does my app crash when importing @expo/ui/swift-ui on Android?

@expo/ui/swift-ui is iOS-only and @expo/ui/jetpack-compose is Android-only; importing either on the wrong platform crashes with 'Unable to get view config' errors. Isolate platform trees in .ios.tsx/.android.tsx files under components/ or guard with Platform.OS.

How do I migrate from @react-native-community/datetimepicker to @expo/ui?

Import the API-compatible drop-in replacement from @expo/ui/community/datetime-picker. Similar drop-ins exist for bottom-sheet, picker, slider, segmented-control, menu, pager-view, and masked-view, usually requiring only an import path change.

Why can't I put .ios.tsx files inside the Expo Router app directory?

Expo Router does not support platform-extension suffixes for route files and throws a 'no fallback sibling' render error. Place platform-specific component files in a components/ directory outside the route tree and import them from regular route files.