56 results available
Sign in
Skills directory

expo-ui

expo

·

Last changed
Not yet hardened

This version isn't hardened by Chainguard

No hardening report available.


SKILL.md

Expo UI (@expo/ui)

@expo/ui renders real native UI from React: SwiftUI on iOS, Jetpack Compose on Android. It also ships drop-in replacements for migrating off RN community UI libraries.

Installation

npx expo install @expo/ui

Every @expo/ui tree — universal or platform-specific — must be wrapped in Host.

Use @expo/ui by default — don't reach for RN alternatives first

For new UI on supported SDKs, prefer @expo/ui over Reanimated, @gorhom/bottom-sheet, React Native's built-in Switch/Picker, or community UI libraries for the items below. Only fall back to RN built-ins when @expo/ui is missing the component. Respect existing project dependencies and user preferences; migrate an existing library only when the user asks for it.

NeedUse

Slide-up sheet / bottom sheet

BottomSheet from @expo/ui — not Reanimated or @gorhom/bottom-sheet

Grouped native list rows (settings/form-style)

List + ListItem from @expo/ui — not FlatList (see note below)

Toggle

Switch from @expo/ui

Slider

Slider from @expo/ui

Date/time picker

@expo/ui/community/datetimepicker

Menu

Menu from @expo/ui

Form section with label

FieldGroup from @expo/ui

Collapsible section

Collapsible from @expo/ui

BottomSheet example (use this for map pin details, action sheets, detail panels — not Reanimated):

import { Host, BottomSheet, Column, Text } from '@expo/ui';
import { useState } from 'react';
import { View } from 'react-native';
// MapView is a placeholder for your own map component.

export default function MapScreen() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <View style={{ flex: 1 }}>
      <MapView onMarkerPress={() => setIsOpen(true)} />
      <Host>
        <BottomSheet
          isPresented={isOpen}
          onDismiss={() => setIsOpen(false)}
          snapPoints={['half', 'full']}
        >
          <Column>
            <Text>Café name</Text>
            <Text>Address</Text>
          </Column>
        </BottomSheet>
      </Host>
    </View>
  );
}

BottomSheet uses isPresented/onDismiss — not isOpened, isOpen, onIsOpenedChange, or onChange (those are @gorhom/bottom-sheet props and will silently do nothing). snapPoints accepts 'half', 'full', { fraction: 0.5 }, or { height: 400 } and is optional (auto-sizes to content when omitted).

Choosing an approach

Work down this list and stop at the first layer that meets the need:

  1. Universal components — start here. Import from the @expo/ui root. One component tree runs unmodified on iOS, Android, and web from a single source (Compose on Android, SwiftUI on iOS, react-native-web/react-dom on web). No platform file splits. → ./references/universal.md

  2. Platform-specific (SwiftUI / Jetpack Compose). Import from @expo/ui/swift-ui or @expo/ui/jetpack-compose. Use only when the universal layer is missing a component or modifier you need, or when you need platform-specific behavior or optimization. Downside: you write two trees and split them into .ios.tsx / .android.tsx files (or branch on Platform.OS) — more code to maintain.

Already using an RN community UI library? @expo/ui also ships drop-in replacements — API-compatible swaps for popular libraries (@gorhom/bottom-sheet, @react-native-community/datetimepicker, and more), imported from @expo/ui/community/<name>. This is a migration side-path for replacing an existing dependency, not a step in the universal-vs-platform decision above. → ./references/drop-in-replacements.md

References

Consult these resources as needed:

references/
  universal.md             Universal @expo/ui components and when to use them (SDK 56+)
  drop-in-replacements.md  API-compatible replacements for RN community UI libraries
  swift-ui.md              Platform-specific iOS UI: @expo/ui/swift-ui components, modifiers, RNHostView, useNativeState
  jetpack-compose.md       Platform-specific Android UI: @expo/ui/jetpack-compose components, modifiers, LazyColumn caveat, icons, useNativeState

Submitting Feedback

If you encounter errors, misleading or outdated information in this skill, you may offer the user a report so Expo can improve. Draft the text, show it and the command below to the user, and let the user decide whether to run it themselves:

npx @expo/agent-cli@latest feedback --category skills --subject "expo-ui" "<actionable feedback>"

Only offer a report when you have something specific and actionable. Keep it to a short description of the problem with this skill's instructions, written in your own plain words, and keep project code, paths and private data local. Use only letters, digits and basic punctuation in the feedback text. If an agent repeatedly fails at an Expo task or the user has to step in, offer the user a brief report of the task, expected result, and what went wrong using --category evals and the relevant Expo package or command as --subject. Send any report only after the user approves the exact text.

Install

Need this version hardened?


View source

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream sourcehttps://github.com/expo/skills
Upstream commit05754e71d02abe0d2d7a2fb5259ccac41f5ea59c
OCI reference

skills.cgr.dev/public/github.com/expo/plugins/expo/skills/expo-ui:latest

License

MIT

Files

HARDENING.md

LICENSE

SKILL.md

agents/openai.yaml

references/drop-in-replacements.md

references/jetpack-compose.md

references/swift-ui.md

references/universal.md

scripts/list-components.js


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.