mcpField
B
building-ui

building-ui

github.com/gigs-slcデザイン・UI379 回インストール39 週間前に更新
リポジトリ

building-ui について

building-uiは、Expo RouterとReact Nativeで画面を構築するためのスキルガイドです。ルーティング、ネイティブコントロール、スタイル、アプリの実行方法を資料と実装指針でまとめ、iOSの慣習に沿った開発を支援します。

主な機能

  1. 01Expo Routerのルート構成規約
  2. 02ネイティブコントロールとナビゲーションの指針
  3. 03アニメーション、メディア、ストレージの資料
  4. 04スタイルとレスポンシブレイアウトの規則
  5. 05Expo Goとカスタムビルドの指針

活用シーン

  1. 01Expoアプリのルート構成の計画
  2. 02画面に使うExpo・React Nativeライブラリの選定
  3. 03画面とセーフエリアに対応するレイアウトの実装
  4. 04カスタムネイティブビルドの要否の判断

インストール

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

$npx skills add https://github.com/gigs-slc/react-native-skills --skill building-ui

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

同梱ファイル

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

references/
animations.md
controls.md
form-sheet.md
gradients.md
icons.md
media.md
route-structure.md
search.md
storage.md
tabs.md
visual-effects.md
webgpu-three.md

詳細

Expo UI ガイドライン

参考資料

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

  • ./references/route-structure.md -- ルートファイルの規則、動的ルート、クエリパラメーター、グループ、フォルダー構成
  • ./references/tabs.md -- NativeTabs を使用したネイティブタブバー、JS タブからの移行、iOS 26 の機能
  • ./references/icons.md -- expo-symbols を使用した SF Symbols、一般的なアイコン名、アニメーション、ウェイト
  • ./references/controls.md -- ネイティブ iOS コントロール:Switch、Slider、SegmentedControl、DateTimePicker、Picker
  • ./references/visual-effects.md -- expo-blur を使用したぼかし効果と、expo-glass-effect を使用したリキッドグラス
  • ./references/animations.md -- Reanimated アニメーション:入場、退場、レイアウト、スクロール駆動、ジェスチャー
  • ./references/search.md -- ヘッダーとの検索バー連携、useSearch フック、フィルタリングのパターン
  • ./references/gradients.md -- experimental_backgroundImage を使用した CSS グラデーション(新アーキテクチャのみ)
  • ./references/media.md -- Expo Router のメディア処理(カメラ、オーディオ、ビデオ、ファイル保存を含む)
  • ./references/storage.md -- SQLite、AsyncStorage、SecureStore を含むデータストレージのパターン
  • ./references/webgpu-three.md -- WebGPU と Three.js を使用した 3D グラフィックス、ゲーム、GPU を活用したビジュアライゼーション

アプリの実行

重要:カスタムビルドを作成する前に、必ず最初に 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 によるウィジェット、アプリクリップ、拡張機能)
  • Expo Go に含まれていないサードパーティ製ネイティブモジュール
  • app.json では指定できないカスタムネイティブ設定
Expo Go が動作する場合

Expo Go は、標準で非常に幅広い機能に対応しています。

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

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

コードスタイル

  • 終端されていない文字列に注意してください。ネストしたバッククォートはエスケープし、引用符も正しくエスケープしてください。
  • ファイルの先頭に必ず import 文を記述してください。
  • ファイル名には必ずケバブケースを使用してください。例: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 を使用してください。
  • @expo/vector-icons ではなく expo-symbols を使用してください。
  • 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 を使用してください。

レスポンシブ対応

  • レスポンシブ対応のため、ルートコンポーネントは必ずスクロールビューでラップしてください
  • よりスマートにセーフエリアのインセットを調整するには、<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 を使用してください
  • 検索バーを追加するには、Stack.Screen のオプションで headerSearchBarOptions を優先してください
  • コピーできるデータを含むテキストには、<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 にパディングを設定する場合は、ScrollView 自体ではなく contentContainerStyle にパディングと gap を設定してください(クリッピングを軽減できます)
  • CSS と Tailwind はサポートされていません。インラインスタイルを使用してください

テキストのスタイリング

  • 重要なデータやエラーメッセージを表示するすべての <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

  • 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, Icon, Label } from "expo-router/unstable-native-tabs";
import { Theme } from "../components/theme";

export default function Layout() {
  return (
    <Theme>
      <NativeTabs>
        <NativeTabs.Trigger name="(index)">
          <Icon sf="list.dash" />
          <Label>Items</Label>
        </NativeTabs.Trigger>
        <NativeTabs.Trigger name="(search)" role="search" />
      </NativeTabs>
    </Theme>
  );
}

両方のタブから共通画面に遷移できるよう、共有グループルートを作成してください。

// app/(index,search)/_layout.tsx
import { Stack } from "expo-router/stack";
import { PlatformColor } from "react-native";

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: PlatformColor("label") },
        headerLargeTitle: true,
        headerBlurEffect: "none",
        headerBackButtonDisplayMode: "minimal",
      }}
    >
      <Stack.Screen name={screen} options={{ title: titles[screen] }} />
      <Stack.Screen name="i/[id]" options={{ headerLargeTitle: false }} />
    </Stack>
  );
}

コメント