mcpField
B
building-native-ui

building-native-ui

github.com/sickn33デザイン・UI48.8k98 回インストール今日更新
リポジトリ

building-native-ui について

Expo アプリでネイティブ UI を構築する開発者向けに、Expo Router のガイドを提供するスキルです。ナビゲーション、スタイル、コンポーネント、アニメーション、プラットフォーム対応、Expo Go と開発ビルドの選択を扱います。

主な機能

  1. 01Expo Router のルートとナビゲーションパターン
  2. 02ネイティブコントロールと UI のスタイル指針
  3. 03アニメーションとジェスチャーのリファレンス
  4. 04レスポンシブレイアウトとセーフエリアの実践
  5. 05Expo Go とカスタムビルドの指針

活用シーン

  1. 01Expo アプリのルート構成
  2. 02ネイティブナビゲーションとフォームシートの構築
  3. 03プラットフォームのテーマに合わせた UI 設計
  4. 04アプリのテストとビルド方法の選択

インストール

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

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill building-native-ui

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

同梱ファイル

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

agents/
openai.yaml
references/
animations.md
controls.md
gradients.md
form-sheet.md
icons.md
route-structure.md
search.md
media.md
visual-effects.md
toolbar-and-headers.md
storage.md
tabs.md
zoom-transitions.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
  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
  route-structure.md     Route conventions, dynamic routes, groups, folder organization
  search.md              Search bar with headers, useSearch hook, filtering patterns
  storage.md             SQLite, AsyncStorage, SecureStore
  tabs.md                NativeTabs, migration from JS tabs, iOS 26 features
  toolbar-and-headers.md Stack headers and toolbar buttons, menus, search (iOS only)
  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
  zoom-transitions.md    Apple Zoom: fluid zoom transitions with Link.AppleZoom (iOS 18+)

アプリの実行

重要: カスタムビルドを作成する前に、必ず最初に 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 のセットアップを必要とします。

コードスタイル

  • 終端されていない文字列に注意してください。ネストされたバッククォートはエスケープされていることを確認し、引用符を正しくエスケープすることを決して忘れないでください。
  • 常にファイルの先頭で import 文を使用してください。
  • ファイル名には常に kebab-case を使用してください (例: comment-card.tsx)
  • ナビゲーションを移動または再構築するときは、常に古いルートファイルを削除してください
  • ファイル名に特殊文字を使用しないでください
  • tsconfig.json をパスエイリアスで設定し、リファクタリングでは相対インポートよりもエイリアスを優先してください。

ルート

詳細なルート規約については、./references/route-structure.md を参照してください。

  • ルートは app ディレクトリに属します。
  • app ディレクトリにコンポーネント、型、ユーティリティを同居させないでください。これはアンチパターンです。
  • アプリには常に "/" に一致するルートがあることを確認してください。それはグループルート内にある場合があります。

ライブラリの推奨

  • Picker、WebView、SafeAreaView、AsyncStorage など、React Native から削除されたモジュールは使用しないでください
  • レガシーの 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 コンポーネント
  • liquid glass の背景には 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" /> を使用してください
  • contentInsetAdjustmentBehavior="automatic" は FlatList と SectionList にも適用してください
  • Dimensions API ではなく flexbox を使用してください
  • 画面サイズを測定するには、Dimensions.get() よりも常に useWindowDimensions を優先してください

動作

  • iOS では expo-haptics を条件付きで使用し、より快適な体験を実現します
  • React Native の <Switch /> や @react-native-community/datetimepicker など、ハプティクスを内蔵したビューを使用します
  • ルートが Stack に属する場合、その最初の子はほぼ常に contentInsetAdjustmentBehavior="automatic" を設定した ScrollView にするべきです
  • ページに ScrollView を追加する場合、ほぼ常にルートコンポーネント内の最初のコンポーネントにするべきです
  • 検索を追加する場合は、Stack.Screen のオプションで headerSearchBarOptions を優先します
  • コピーされる可能性のあるデータを含むテキストには <Text selectable /> プロパティを使用します
  • 1.4M や 38k のような大きな数値のフォーマットを検討します
  • webview または Expo DOM コンポーネント内でない限り、'img' や 'div' のような intrinsic 要素は決して使用しないでください

スタイリング

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

一般的なスタイリングルール

  • margin や padding スタイルよりも flex gap を優先します
  • 可能な場合は margin よりも padding を優先します
  • 常にセーフエリアを考慮します。スタックヘッダー、タブ、または ScrollView/FlatList の contentInsetAdjustmentBehavior="automatic" のいずれかを使用します
  • 上部と下部の両方のセーフエリアインセットが考慮されていることを確認します
  • スタイルの再利用が速い場合を除き、StyleSheet.create ではなくインラインスタイルを使用します
  • 状態変化に対して entering および exiting アニメーションを追加します
  • カプセル形状を作成する場合を除き、角丸には { borderCurve: 'continuous' } を使用します
  • ページ上のカスタムテキスト要素ではなく、常にナビゲーションスタックのタイトルを使用します
  • ScrollView に padding を適用する場合は、ScrollView 自体に padding を適用するのではなく、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 用の default 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' シャドウもサポートされています。

ナビゲーション

Link

ルート間のナビゲーションには 'expo-router' の <Link href="/path" /> を使用します。

import { Link } from 'expo-router';

// Basic link
<Link href="/path" />

// Wrapping custom components
<Link href="/path" asChild>
  <Pressable>...</Pressable>
</Link>

可能な限り、iOS の慣習に従うために <Link.Preview> を含めます。ナビゲーションを強化するために、コンテキストメニューとプレビューを頻繁に追加します。

Stack

  • スタックを定義するには常に _layout.tsx ファイルを使用します
  • ネイティブナビゲーションスタックには 'expo-router/stack' の Stack を使用します
ページタイトル

Stack.Screen のオプションでページタイトルを設定します:

<Stack.Screen options={{ title: "Home" }} />

コンテキストメニュー

Link コンポーネントに長押しのコンテキストメニューを追加します:

import { Link } from "expo-router";

<Link href="/settings" asChild>
  <Link.Trigger>
    <Pressable>
      <Card />
    </Pressable>
  </Link.Trigger>
  <Link.Menu>
    <Link.MenuAction
      title="Share"
      icon="square.and.arrow.up"
      onPress={handleSharePress}
    />
    <Link.MenuAction
      title="Block"
      icon="nosign"
      destructive
      onPress={handleBlockPress}
    />
    <Link.Menu title="More" icon="ellipsis">
      <Link.MenuAction title="Copy" icon="doc.on.doc" onPress={() => {}} />
      <Link.MenuAction
        title="Delete"
        icon="trash"
        destructive
        onPress={() => {}}
      />
    </Link.Menu>
  </Link.Menu>
</Link>;

リンクプレビュー

ナビゲーションを強化するために、リンクプレビューを頻繁に使用します:

<Link href="/settings">
  <Link.Trigger>
    <Pressable>
      <Card />
    </Pressable>
  </Link.Trigger>
  <Link.Preview />
</Link>

リンクプレビューはコンテキストメニューと組み合わせて使用できます。

モーダル

画面をモーダルとして表示します:

<Stack.Screen name="modal" options={{ presentation: "modal" }} />

カスタムモーダルコンポーネントを構築するよりも、こちらを優先してください。

シート

画面を動的なフォームシートとして表示します:

<Stack.Screen
  name="sheet"
  options={{
    presentation: "formSheet",
    sheetGrabberVisible: true,
    sheetAllowedDetents: [0.5, 1.0],
    contentStyle: { backgroundColor: "transparent" },
  }}
/>
  • contentStyle: { backgroundColor: "transparent" } を使用すると、iOS 26 以降で背景がリキッドグラスになります。

共通のルート構造

各タブ内にタブとスタックを備えた標準的なアプリレイアウト:

app/
  _layout.tsx — <NativeTabs />
  (index,search)/
    _layout.tsx — <Stack />
    index.tsx — Main list
    search.tsx — Search view
// app/_layout.tsx
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 (
    <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
      <NativeTabs>
        <NativeTabs.Trigger name="(index)">
          <NativeTabs.Trigger.Icon sf="list.dash" md="list" />
          <NativeTabs.Trigger.Label>Items</NativeTabs.Trigger.Label>
        </NativeTabs.Trigger>
        <NativeTabs.Trigger name="(search)" role="search" />
      </NativeTabs>
    </ThemeProvider>
  );
}

両方のタブが共通の画面をプッシュできるように、共有グループルートを作成します:

// app/(index,search)/_layout.tsx
import { Stack } from "expo-router/stack";
import { colors } from "@/theme/colors";

export default function Layout({ segment }) {
  const screen = segment.match(/\((.*)\)/)?.[1]!;
  const titles: Record<string, string> = { index: "Items", search: "Search" };

  return (
    <Stack
      screenOptions={{
        headerTransparent: true,
        headerShadowVisible: false,
        headerLargeTitleShadowVisible: false,
        headerLargeStyle: { backgroundColor: "transparent" },
        headerTitleStyle: { color: colors.label },
        headerLargeTitle: true,
        headerBlurEffect: "none",
        headerBackButtonDisplayMode: "minimal",
      }}
    >
      <Stack.Screen name={screen} options={{ title: titles[screen] }} />
      <Stack.Screen name="i/[id]" options={{ headerLargeTitle: false }} />
    </Stack>
  );
}

制限事項

  • このスキルは、タスクがその上流製品または API の範囲に明確に一致する場合にのみ使用してください。
  • 変更を加える前に、コマンド、API の動作、料金、クォータ、認証情報、デプロイへの影響を最新の公式ドキュメントで確認してください。
  • 生成された例を、環境固有のテスト、セキュリティレビュー、または破壊的あるいは高コストな操作に対するユーザーの承認の代わりとして扱わないでください。

コメント