📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -2,17 +2,19 @@
|
||||
name: building-native-ui
|
||||
description: Complete guide for building beautiful apps with Expo Router. Covers fundamentals, styling, components, navigation, animations, patterns, and native tabs.
|
||||
risk: unknown
|
||||
source: community
|
||||
version: 1.0.1
|
||||
source: https://github.com/expo/skills/tree/main/plugins/expo/skills/building-native-ui
|
||||
source_repo: expo/skills
|
||||
source_type: official
|
||||
date_added: 2026-07-01
|
||||
license: MIT
|
||||
license_source: https://github.com/expo/skills/blob/main/LICENSE
|
||||
---
|
||||
|
||||
# Expo UI Guidelines
|
||||
|
||||
## When to Use
|
||||
- You are building a native-feeling Expo Router application and need guidance on navigation, controls, effects, or platform-specific UI.
|
||||
- You need to decide whether Expo Go is sufficient or a custom native build is actually required.
|
||||
- The task involves modern Expo UI patterns across animations, tabs, headers, storage, media, or visual effects.
|
||||
|
||||
Use this skill when you need complete guide for building beautiful apps with Expo Router. Covers fundamentals, styling, components, navigation, animations, patterns, and native tabs.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
@@ -22,7 +24,7 @@ Consult these resources as needed:
|
||||
references/
|
||||
animations.md Reanimated: entering, exiting, layout, scroll-driven, gestures
|
||||
controls.md Native iOS: Switch, Slider, SegmentedControl, DateTimePicker, Picker
|
||||
form-sheet.md Form sheets in expo-router: configuration, footers and background interaction.
|
||||
form-sheet.md Form sheets in expo-router: configuration, footers and background interaction.
|
||||
gradients.md CSS gradients via experimental_backgroundImage (New Arch only)
|
||||
icons.md SF Symbols via expo-image (sf: source), names, animations, weights
|
||||
media.md Camera, audio, video, and file saving
|
||||
@@ -95,6 +97,8 @@ See `./references/route-structure.md` for detailed route conventions.
|
||||
- `React.use` not `React.useContext`
|
||||
- `expo-image` Image component instead of intrinsic element `img`
|
||||
- `expo-glass-effect` for liquid glass backdrops
|
||||
- `Color` from `expo-router` for native semantic colors, not raw `PlatformColor` (type-safe, auto-adapts to light/dark)
|
||||
- In SDK 56+, never import from `@react-navigation/*` directly — use `expo-router/react-navigation` instead (covers `@react-navigation/native`, `/core`, `/elements`, `/routers`)
|
||||
|
||||
## Responsiveness
|
||||
|
||||
@@ -132,6 +136,58 @@ Follow Apple Human Interface Guidelines.
|
||||
- When padding a ScrollView, use `contentContainerStyle` padding and gap instead of padding on the ScrollView itself (reduces clipping)
|
||||
- CSS and Tailwind are not supported - use inline styles
|
||||
|
||||
## Colors
|
||||
|
||||
Use the `Color` API from `expo-router` for native semantic colors. It is a type-safe wrapper over `PlatformColor` that exposes iOS UIKit colors through `Color.ios.*` and Android Material 3 colors through `Color.android.material.*` (static) or `Color.android.dynamic.*` (adapts to the user's wallpaper on Android 12+). These resolve on-device and automatically adapt to light/dark mode and accessibility settings, so you no longer maintain separate light/dark hex tables or a `colors.web.ts` file.
|
||||
|
||||
`Color` is platform-specific, so wrap each value in `Platform.select` with a `default` hex fallback for web. Centralize the palette in `theme/colors.ts` and import `colors` everywhere:
|
||||
|
||||
```tsx
|
||||
// theme/colors.ts
|
||||
import { Platform } from "react-native";
|
||||
import { Color } from "expo-router";
|
||||
|
||||
export const colors = {
|
||||
label: Platform.select({
|
||||
ios: Color.ios.label,
|
||||
android: Color.android.dynamic.onSurface,
|
||||
default: "#000000",
|
||||
})!,
|
||||
secondaryLabel: Platform.select({
|
||||
ios: Color.ios.secondaryLabel,
|
||||
android: Color.android.dynamic.onSurfaceVariant,
|
||||
default: "#3c3c43",
|
||||
})!,
|
||||
separator: Platform.select({
|
||||
ios: Color.ios.separator,
|
||||
android: Color.android.dynamic.outlineVariant,
|
||||
default: "#c6c6c8",
|
||||
})!,
|
||||
systemBackground: Platform.select({
|
||||
ios: Color.ios.systemBackground,
|
||||
android: Color.android.dynamic.surface,
|
||||
default: "#ffffff",
|
||||
})!,
|
||||
systemBlue: Platform.select({
|
||||
ios: Color.ios.systemBlue,
|
||||
android: Color.android.dynamic.primary,
|
||||
default: "#007aff",
|
||||
})!,
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
import { colors } from "@/theme/colors";
|
||||
|
||||
<View style={{ backgroundColor: colors.systemBackground }}>
|
||||
<Text style={{ color: colors.label }}>Title</Text>
|
||||
</View>;
|
||||
```
|
||||
|
||||
- iOS re-resolves these colors automatically when the system theme changes. On Android, call `useColorScheme()` inside any component that renders them so it re-renders when the theme flips (required when React Compiler memoizes the component).
|
||||
- Don't pass `Color` / `PlatformColor` values into Reanimated styles — use static colors there (see `references/animations.md`).
|
||||
- `Platform.select({...})!` returns `string | OpaqueColorValue`. Most React Native style props accept `ColorValue` (`string | OpaqueColorValue`) so this works fine. But some third-party props only accept `string` (e.g. `tintColor` on `expo-image`). Cast when needed: `colors.label as string`.
|
||||
|
||||
## Text Styling
|
||||
|
||||
- Add the `selectable` prop to every `<Text/>` element displaying important data or error messages
|
||||
@@ -278,20 +334,22 @@ app/
|
||||
|
||||
```tsx
|
||||
// app/_layout.tsx
|
||||
import { NativeTabs, Icon, Label } from "expo-router/unstable-native-tabs";
|
||||
import { Theme } from "../components/theme";
|
||||
import { NativeTabs } from "expo-router/unstable-native-tabs";
|
||||
import { ThemeProvider, DarkTheme, DefaultTheme } from "expo-router/react-navigation";
|
||||
import { useColorScheme } from "react-native";
|
||||
|
||||
export default function Layout() {
|
||||
const colorScheme = useColorScheme();
|
||||
return (
|
||||
<Theme>
|
||||
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
||||
<NativeTabs>
|
||||
<NativeTabs.Trigger name="(index)">
|
||||
<Icon sf="list.dash" />
|
||||
<Label>Items</Label>
|
||||
<NativeTabs.Trigger.Icon sf="list.dash" md="list" />
|
||||
<NativeTabs.Trigger.Label>Items</NativeTabs.Trigger.Label>
|
||||
</NativeTabs.Trigger>
|
||||
<NativeTabs.Trigger name="(search)" role="search" />
|
||||
</NativeTabs>
|
||||
</Theme>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -301,7 +359,7 @@ Create a shared group route so both tabs can push common screens:
|
||||
```tsx
|
||||
// app/(index,search)/_layout.tsx
|
||||
import { Stack } from "expo-router/stack";
|
||||
import { PlatformColor } from "react-native";
|
||||
import { colors } from "@/theme/colors";
|
||||
|
||||
export default function Layout({ segment }) {
|
||||
const screen = segment.match(/\((.*)\)/)?.[1]!;
|
||||
@@ -314,7 +372,7 @@ export default function Layout({ segment }) {
|
||||
headerShadowVisible: false,
|
||||
headerLargeTitleShadowVisible: false,
|
||||
headerLargeStyle: { backgroundColor: "transparent" },
|
||||
headerTitleStyle: { color: PlatformColor("label") },
|
||||
headerTitleStyle: { color: colors.label },
|
||||
headerLargeTitle: true,
|
||||
headerBlurEffect: "none",
|
||||
headerBackButtonDisplayMode: "minimal",
|
||||
@@ -328,6 +386,7 @@ export default function Layout({ segment }) {
|
||||
```
|
||||
|
||||
## Limitations
|
||||
- Use this skill only when the task clearly matches the scope described above.
|
||||
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
|
||||
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
|
||||
|
||||
- Use this skill only when the task clearly matches its upstream product or API scope.
|
||||
- Verify commands, API behavior, pricing, quotas, credentials, and deployment effects against current official documentation before making changes.
|
||||
- Do not treat generated examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
|
||||
|
||||
Reference in New Issue
Block a user