mcpField
B
building-native-ui

building-native-ui

github.com/expoデザイン・UI3.5k58.1k 回インストール今日更新
リポジトリ

building-native-ui について

building-native-ui は Expo と React Native の UI 開発ガイドで、ネイティブコントロール、スタイル、レイアウト、操作を扱います。参考資料やコード規約に加え、Expo Go とカスタムビルドの使い分けも説明します。

主な機能

  1. 01ネイティブコントロールとアニメーションの資料
  2. 02レイアウトとレスポンシブ設計の指針
  3. 03プラットフォームのセマンティックカラー利用
  4. 04スタイルとコーディング規約
  5. 05Expo Go とカスタムビルドの指針

活用シーン

  1. 01Expo ルートの UI 構築
  2. 02ネイティブコントロールとアニメーションの実装
  3. 03画面サイズに応じたレイアウト対応
  4. 04カスタムネイティブビルドの要否判断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/expo/skills --skill building-native-ui

インストール後、Claude Code で/building-native-uiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
animations.md
controls.md
gradients.md
icons.md
media.md
storage.md
visual-effects.md
webgpu-three.md

詳細

Expo UI ガイドライン

ルート、リンク、スタック、タブ、モーダル、シート、ヘッダーには、expo-router スキルを使用してください。

参考資料

必要に応じて、以下のリソースを参照してください。

references/
  animations.md          Reanimated: entering, exiting, layout, scroll-driven, gestures
  controls.md            Native iOS: Switch, Slider, SegmentedControl, DateTimePicker, Picker
  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
  storage.md             SQLite, AsyncStorage, SecureStore
  visual-effects.md      Blur (expo-blur) and liquid glass (expo-glass-effect)
  webgpu-three.md        3D graphics, games, GPU visualizations with WebGPU and Three.js

アプリの実行

重要:カスタムビルドを作成する前に、必ず Expo Go を試してください。

ほとんどの Expo アプリは、カスタムネイティブコードなしで Expo Go で動作します。npx expo run:ios または npx expo run:android を実行する前に、次の手順を行ってください。

  1. まず Expo Go を起動する:npx expo start を実行し、Expo Go で QR コードをスキャンします
  2. 機能が動作するか確認する:Expo Go でアプリを十分にテストします
  3. 必要な場合にのみカスタムビルドを作成する:詳細は以下を参照してください
カスタムビルドが必要な場合

以下を使用する場合に限り、npx expo run:ios/android または eas build が必要です。

  • ローカル Expo モジュール(modules/ 内のカスタムネイティブコード)
  • Apple ターゲット(@bacons/apple-targets を介したウィジェット、App Clip、拡張機能)
  • Expo Go に含まれていないサードパーティ製ネイティブモジュール
  • app.json では表現できないカスタムネイティブ設定
Expo Go が使える場合

Expo Go は、すぐに使える幅広い機能に対応しています。

  • すべての expo-* パッケージ(カメラ、位置情報、通知など)
  • Expo Router のナビゲーション
  • ほとんどの UI ライブラリ(reanimated、gesture handler など)
  • プッシュ通知、ディープリンクなど

迷った場合は、まず Expo Go を試してください。 カスタムビルドを作成すると複雑さが増し、開発サイクルが遅くなるうえ、Xcode/Android Studio のセットアップが必要になります。

コードスタイル

  • 文字列の閉じ忘れに注意してください。ネストされたバッククォートはエスケープし、引用符も必ず正しくエスケープしてください。
  • インポート文は必ずファイルの先頭に記述してください。
  • ファイル名には必ずケバブケースを使用してください。例:comment-card.tsx
  • ファイル名に特殊文字を使用しないでください。
  • tsconfig.json でパスエイリアスを設定し、リファクタリングでは相対インポートよりエイリアスを優先してください。

ライブラリの選択

  • React Native から削除された Picker、WebView、SafeAreaView、AsyncStorage などのモジュールは使用しないでください。
  • レガシーの expo-permissions は使用しないでください。
  • expo-av ではなく expo-audio を使用してください。
  • expo-av ではなく expo-video を使用してください。
  • SF Symbols には expo-symbols や @expo/vector-icons ではなく、source="sf:name" を指定した expo-image を使用してください。
  • react-native の SafeAreaView ではなく react-native-safe-area-context を使用してください。
  • Platform.OS ではなく process.env.EXPO_OS を使用してください。
  • React.useContext ではなく React.use を使用してください。
  • 組み込み要素の img ではなく、expo-image の Image コンポーネントを使用してください。
  • 液体ガラスの背景には expo-glass-effect を使用してください。
  • ネイティブのセマンティックカラーには、生の PlatformColor ではなく、expo-router の Color を使用してください(型安全で、ライト/ダークモードに自動適応します)。
  • SDK 56 以降では、@react-navigation/* から直接インポートしないでください。代わりに expo-router/react-navigation を使用してください(@react-navigation/native、/core、/elements、/routers をカバーします)。

レスポンシブ対応

  • ルートコンポーネントは必ずスクロールビューで囲み、レスポンシブにしてください。
  • より適切なセーフエリアのインセットを得るには、<SafeAreaView> の代わりに <ScrollView contentInsetAdjustmentBehavior="automatic" /> を使用してください。
  • FlatList と SectionList にも contentInsetAdjustmentBehavior="automatic" を適用してください。
  • Dimensions API ではなく、Flexbox を使用してください。
  • 画面サイズの測定には、常に Dimensions.get() より useWindowDimensions を優先してください。

動作

  • より快適な体験を提供するため、iOS では条件に応じて expo-haptics を使用してください。
  • React Native の <Switch /> や @react-native-community/datetimepicker など、触覚フィードバックが組み込まれたビューを使用してください。
  • ルートがスタックに属する場合、最初の子要素はほとんどの場合、contentInsetAdjustmentBehavior="automatic" を設定した ScrollView にしてください。
  • ページに ScrollView を追加する場合、ほとんどの場合、ルートコンポーネント内の最初のコンポーネントにしてください。
  • コピーできるデータを含むテキストには、<Text selectable /> プロパティを使用してください。
  • 1.4M や 38k のように、大きな数値の表記を整えることを検討してください。
  • WebView または Expo DOM コンポーネント内でない限り、'img' や 'div' などの組み込み要素は使用しないでください。

スタイリング

Apple Human Interface Guidelines に従ってください。

全般的なスタイルルール

  • margin や padding のスタイルより、flex の gap を優先します
  • 可能な場合は、margin より padding を優先します
  • stack ヘッダー、タブ、または ScrollView/FlatList の contentInsetAdjustmentBehavior="automatic" を使い、常にセーフエリアを考慮します
  • 上下両方のセーフエリアのインセットを必ず考慮します
  • スタイルを再利用するほうが効率的な場合を除き、StyleSheet.create ではなくインラインスタイルを使います
  • 状態変化には、必ず入場アニメーションと退場アニメーションを追加します
  • カプセル形状を作成する場合を除き、角を丸くするときは { borderCurve: 'continuous' } を使います
  • ページ上のカスタムテキスト要素ではなく、必ずナビゲーションスタックのタイトルを使います
  • ScrollView に padding を設定する場合は、ScrollView 自体ではなく contentContainerStyle に padding と gap を指定します(クリッピングを軽減できます)
  • CSS と Tailwind はサポートされていません。インラインスタイルを使ってください

色

ネイティブのセマンティックカラーには、expo-router の Color API を使います。これは PlatformColor の型安全なラッパーで、iOS UIKit のカラーを Color.ios.*、Android Material 3 のカラーを Color.android.material.*(静的)または Color.android.dynamic.*(Android 12 以降でユーザーの壁紙に適応)から利用できます。これらはデバイス上で解決され、ライト/ダークモードとアクセシビリティ設定に自動的に適応するため、ライト/ダーク別の hex テーブルや colors.web.ts ファイルを個別に管理する必要はありません。

Color はプラットフォーム固有のため、各値を Platform.select でラップし、Web 用のデフォルトの hex 値を指定します。パレットは theme/colors.ts にまとめ、どこでも colors をインポートしてください:

// 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",
  })!,
};
import { colors } from "@/theme/colors";

<View style={{ backgroundColor: colors.systemBackground }}>
  <Text style={{ color: colors.label }}>Title</Text>
</View>;
  • iOS では、システムテーマが変わるとこれらの色が自動的に再解決されます。Android では、これらの色を描画するコンポーネント内で useColorScheme() を呼び出すと、テーマが切り替わったときに再レンダリングされます(React Compiler がコンポーネントをメモ化する場合に必要です)。
  • Color/PlatformColor の値を Reanimated のスタイルに渡さないでください。代わりに静的な色を使います(references/animations.md を参照)。
  • Platform.select({...})! は string | OpaqueColorValue を返します。ほとんどの React Native のスタイルプロパティは ColorValue(string | OpaqueColorValue)を受け付けるため、問題なく使えます。ただし、一部のサードパーティ製プロパティは string のみを受け付けます(例:expo-image の tintColor)。必要に応じてキャストしてください:colors.label as string。

テキストのスタイル

  • 重要なデータやエラーメッセージを表示するすべての <Text/> 要素に、selectable プロパティを追加します
  • カウンターは、値を揃えるために { fontVariant: 'tabular-nums' } を使います

シャドウ

CSS の boxShadow スタイルプロパティを使います。従来の React Native の shadow または elevation スタイルは絶対に使わないでください。

<View style={{ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)" }} />

'inset' シャドウはサポートされています。

コメント