expo-design-system について
Unistyles v3 を使う Expo/React Native アプリ向けのデザインシステム設計スキルです。clinic アプリの構成に沿って、Web と iOS の共通コンポーネントを整備するチームを支援します。
主な機能
- 01Unistyles テーマでトークンを管理
- 02バリアントとスロットを軸に API を設計
- 03Web と iOS の動作を統一
- 04UI スレッドでのアニメーションとジェスチャーを指針化
- 05共有コンポーネントと再利用を管理
活用シーン
- 01Expo アプリのデザインシステムを構築
- 02場当たり的なスタイルをトークンへ移行
- 03スタイルと API の一貫性をレビュー
- 04Web と iOS の共通コンポーネントを構築
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill expo-design-systemインストール後、Claude Code で/expo-design-systemを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdmetadata.jsonassets/templates/_template.mdreferences/_sections.mdapi-accessibility-in-contract.mdapi-aschild-polymorphism.mdapi-compound-variants.mdapi-controlled-uncontrolled.mdapi-forward-ref.mdapi-no-style-escape-hatch.mdapi-slots-for-composition.mdapi-variants-over-style-prop.mddomain-bodychart-gesture-paths.mddomain-bodychart-skia-canvas.mddomain-calendar-virtualization.mddomain-compose-from-primitives.mddomain-note-editor-autosave.mddomain-optimistic-writes.mdgovern-design-system-package.mdgovern-incremental-migration.mdgovern-lint-no-raw-values.mdgovern-naming-conventions.mdgovern-prevent-local-tokens.mdgovern-storybook-catalog.mdperf-defer-offscreen-work.mdperf-expo-image.mdperf-flashlist-for-lists.mdperf-gesture-handler.mdperf-haptics-key-actions.mdperf-memoize-list-items.md詳細
Airbnb DLS Expo React Native デザインシステムのベストプラクティス
Expo/React Native アプリ向けの、意見を明確にした厳格なデザインシステムエンジニアリングです。New Architecture 上で、Web とネイティブ iOS の両方を対象としています。影響度に応じて優先順位付けされた、11 カテゴリにわたる 63 のルールを含みます。Airbnb の Design Language System(DLS)、Unistyles v3 のドキュメント、React Native エコシステム(Reanimated、Gesture Handler、Skia、FlashList、Expo SDK)を基にしています。スタイリングエンジンには Unistyles v3 を使用し、コンポーネント API では、スタイルの回避手段よりもバリアント props を優先する Airbnb DLS のパターンに従います。
必須のアーキテクチャ整合性
このスキルはインフラストラクチャ層です。デザインシステム自体の構築方法を説明するもので、ios-design-system の React Native 版に相当します。すべてのコード例は、次の変更不可の制約に従います。
- 機能モジュールがインポートするのは
@clinic/design-systemとdomainのみです。他の機能の内部実装はインポートしません - デザインシステムが Unistyles のテーマ(トークン、ブレークポイント)を管理し、厳選された公開 API をエクスポートします
- 実装する前に再利用を検討します。インデックスを読み、バリアントを拡張し、2 回目の使用時に昇格させます。ローカルに並行コンポーネントを作ることはありません
- コンポーネントはバリアントとスロットの props を公開します(Airbnb DLS)。生の
styleによる回避手段はありません - アニメーションとジェスチャーは UI スレッドで実行します(Reanimated の worklet と Gesture Handler)
- リストには FlashList を使用し、ボディチャートの描画面には React Native Skia を使用します
- 1 つのソースで Web と iOS の両方にネイティブな操作感を実現します。Unistyles の
_web疑似状態とPlatformによる分岐を使用し、Web 用スタイルシートを分岐して作りません - New Architecture(Fabric/JSI)、Expo SDK 53 以降/React Native 0.81 以降を対象とします
対象範囲と関連する兄弟スキル
| 兄弟スキル | そのスキルの対象 | このスキルの対象 |
|---|---|---|
ios-design-system | 同じクリニックアプリ向けの SwiftUI デザインシステム | Expo/React Native 版 |
expo-react-native-coder | 機能開発(画面、ナビゲーション、データ取得) | デザインシステムのインフラストラクチャ(トークン、コンポーネント、テーマ設定) |
expo-react-native-performance | アプリ全体のパフォーマンス最適化 | デザインシステム内でネイティブな操作感を実現するためのパフォーマンス |
react | 一般的な React パターン | Expo/React Native のデザインシステム固有の内容 |
expo-ios-hig | iOS ネイティブの操作感に関する判断(ナビゲーション、システムコントロール、Liquid Glass) | クロスプラットフォームのトークン/コンポーネントアーキテクチャと Web/iOS の一貫性 |
クリニックのアーキテクチャ契約(Expo/React Native)
このスキルのすべてのガイダンスは、クリニックのモジュール型アーキテクチャを前提としています。
- 機能モジュールが依存するのは
@clinic/design-systemとdomainのみです。アプリのターゲットがナビゲーション(Expo Router)と依存性注入を組み立てます - デザインシステムは公開エントリが 1 つだけのローカルパッケージです。生のトークンレイヤーは非公開のままにします
- トークンの信頼できる情報源は Unistyles のテーマです。機能がローカルトークンを定義することはありません
- サーバー状態には TanStack Query を使用します。読み取りはデフォルトで stale-while-revalidate とし、書き込みは楽観的に処理してオフライン同期用にキューイングします
- Unistyles v3、Reanimated の worklet、Skia、FlashList v2 を使用するには、New Architecture が必須です
適用する場面
以下の場合に、これらのガイドラインを参照してください。
- 新しい Expo/React Native アプリのデザインシステムを設定するとき
- Unistyles のテーマでトークンアーキテクチャ(色、タイポグラフィ、スペーシング、角丸、エレベーション)を構築するとき
- コンポーネント API(バリアント、スロット、制御状態/非制御状態、ref、アクセシビリティ)を設計するとき
- Unistyles StyleSheet、バリアント、動的関数を使ってコンポーネントのスタイルを定義するとき
- カレンダー、施術記録エディター、または Skia のボディチャート描画サーフェスを構築するとき
- 場当たり的なスタイルを、管理されたトークンシステムに移行するとき
- 生の色、インラインスタイル、漏れ出した
styleプロパティ、または機能内限定のトークンについて PR をレビューするとき - リストの仮想化、UI スレッド上のアニメーション、ジェスチャー、触覚フィードバック、セーフエリアなど、ネイティブらしい操作感を調整するとき
- Web と iOS の両方でコンポーネントをネイティブにレンダリングし、自然に操作できるようにするとき — ホバー/フォーカス/カーソル、
Platformによる分岐、セーフエリア/触覚フィードバックの差異を含みます - 新規構築と再利用のどちらが適切か判断するとき — デザインシステムのインデックスを確認し、拡張するかフォークするかを検討し、ネイティブまたは
@expo/uiのコントロールを再実装する代わりに使用するときを含みます
優先度別のルールカテゴリー
| 優先度 | カテゴリー | 影響度 | プレフィックス | ルール数 |
|---|---|---|---|---|
| 1 | トークンアーキテクチャ | CRITICAL | token- | 6 |
| 2 | テーマ設定と適応性 | CRITICAL | theme- | 5 |
| 3 | コンポーネント API の契約 | CRITICAL | api- | 8 |
| 4 | クロスプラットフォームの同等性 | CRITICAL | platform- | 5 |
| 5 | 再利用とシステムへの適合性 | HIGH | reuse- | 4 |
| 6 | スタイリングエンジン(Unistyles) | HIGH | style- | 6 |
| 7 | タイポグラフィとアイコノグラフィ | HIGH | type- | 5 |
| 8 | スペーシング、レイアウト、セーフエリア | HIGH | space- | 5 |
| 9 | ネイティブらしい操作感とパフォーマンス | HIGH | perf- | 7 |
| 10 | 複雑なドメインコンポーネント | MEDIUM-HIGH | domain- | 6 |
| 11 | ガバナンスと一貫性 | MEDIUM | govern- | 6 |
クイックリファレンス
1. トークンアーキテクチャ(CRITICAL)
token-three-layer-scale- トークンを生の値、セマンティック、コンポーネントの3つのスケールに分けますtoken-define-in-unistyles-theme- Unistyles のテーマを唯一のトークンソースとして維持しますtoken-no-raw-values-in-components- すべての色とサイズをトークン経由で指定しますtoken-semantic-naming- 値ではなく役割に基づいてトークンに名前を付けますtoken-elevation-pairs- エレベーションをサーフェスとシャドウのペアとしてトークン化しますtoken-avoid-over-abstraction- トークンのレイヤーは3つまでにします
2. テーマ設定と適応性(CRITICAL)
theme-runtime-not-rerender- 再レンダリングせず、ランタイム経由でテーマを切り替えますtheme-stylesheet-theme-arg- StyleSheet の引数からテーマを読み取りますtheme-adaptive-system- デフォルトでシステムのカラースキームに従いますtheme-breakpoints-responsive- Dimensions のチェックではなく、ブレークポイントを使用しますtheme-config-single-module- テーマとブレークポイントを1つの型付き設定モジュールにまとめます
3. コンポーネント API コントラクト(CRITICAL)
api-variants-over-style-prop- 視覚的なオプションはバリアントの props として表現しますapi-no-style-escape-hatch- コンポーネントに生の style prop を設けませんapi-compound-variants- 組み合わせごとにコンポーネントを作るのではなく、複合バリアントを使用しますapi-slots-for-composition- 要素ごとに prop を設けるのではなく、スロット props を使用しますapi-controlled-uncontrolled- 制御状態と非制御状態の両方をサポートしますapi-forward-ref- リーフコンポーネントから ref を転送しますapi-accessibility-in-contract- コントラクトでアクセシビリティ用 props を必須にしますapi-aschild-polymorphism- ラッパーをネストするのではなく、asChild を提供します
4. クロスプラットフォームの同等性(CRITICAL)
platform-web-pseudo-states- インタラクティブなコンポーネントに、Web の hover、focus、cursor を追加しますplatform-guard-native-only- ネイティブ専用 API を Platform チェックでガードし、Web 用のフォールバックを用意しますplatform-divergence-split- プラットフォーム間の違いを単一のコンポーネント API の背後に分離しますplatform-input-model- ポインターとタッチを前提に設計し、hover のみに依存しないようにしますplatform-shared-theme-parity- Web とネイティブで単一のテーマを使用し、既知の差異をマップにまとめます
5. 再利用とシステムとの整合性(HIGH)
reuse-inventory-first- スタイルを書く前に、デザインシステムのインデックスを確認しますreuse-extend-not-fork- ローカル用にコンポーネントをフォークするのではなく、バリアントを追加して共有コンポーネントを拡張しますreuse-promote-on-second-use- パターンが2回目に使われたら、システムに取り込みますreuse-platform-component-first- 再実装する前に、ネイティブコントロールの利用を検討します
6. スタイリングエンジン(Unistyles)(HIGH)
style-stylesheet-create- インラインオブジェクトではなく StyleSheet.create を使用しますstyle-variants-api- 三項演算子によるスタイル配列ではなく、バリアントを使用しますstyle-dynamic-functions- prop によって値が変わる場合は、動的関数を使用しますstyle-no-inline-array-merge- リスト内でインラインの配列結合を行いませんstyle-withunistyles-third-party- withUnistyles でサードパーティ製コンポーネントにテーマを適用しますstyle-press-states-from-variants- 押下状態と無効状態をバリアントとして扱います
7. タイポグラフィとアイコン(HIGH)
type-scale-tokens- 名前付きのタイポグラフィスケールを定義しますtype-respect-font-scaling- OS のフォント拡大縮小設定に従いますtype-text-component-wrapper- テキストを単一の型付きコンポーネント経由で処理しますtype-font-loading-expo-font- 初回描画前にフォントを読み込みますtype-icon-registry- アイコンを型付きレジストリに集約します
8. 間隔、レイアウト、安全領域(高)
space-spacing-scale- 4ptグリッドの間隔スケールを使用しますspace-safe-area-insets- 画面端にセーフエリアのインセットを適用しますspace-touch-targets- タッチターゲットを少なくとも44ポイントのサイズにしますspace-gap-over-margins- 子要素ごとにマージンを設定する代わりに、gapを使用しますspace-radius-tokens- 役割ごとに角丸のトークンを定義します
9. ネイティブな操作感とパフォーマンス(高)
perf-flashlist-for-lists- ScrollViewのリストではなくFlashListを使用しますperf-reanimated-ui-thread- UIスレッド上でアニメーションを実行しますperf-gesture-handler- PanResponderではなくGesture Handlerを使用しますperf-expo-image- expo-imageとキャッシュを使って画像を読み込みますperf-memoize-list-items- 行とコールバックをメモ化しますperf-haptics-key-actions- 確認や切り替え時に触覚フィードバックを追加しますperf-defer-offscreen-work- トランジション後まで処理を遅らせます
10. 複雑なドメインコンポーネント(中〜高)
domain-calendar-virtualization- 予約カレンダーを日ごとに仮想化しますdomain-note-editor-autosave- オフラインファーストのデバウンス付きノート自動保存domain-bodychart-skia-canvas- Skiaキャンバスにボディチャートを描画しますdomain-bodychart-gesture-paths- ジェスチャーと共有値を使ってストロークをキャプチャしますdomain-compose-from-primitives- プリミティブからドメインコンポーネントを構築しますdomain-optimistic-writes- 書き込み時に楽観的UIを表示します
11. ガバナンスと一貫性(中)
govern-design-system-package- デザインシステムを単一のエントリーポイントでパッケージ化しますgovern-lint-no-raw-values- 色の直接指定とインラインスタイルをLintで検出しますgovern-prevent-local-tokens- 機能ごとのローカルトークンを防ぎますgovern-storybook-catalog- Storybookでコンポーネントのバリエーションを一覧化しますgovern-naming-conventions- 命名規則を統一しますgovern-incremental-migration- トークンへ段階的に移行します
使用方法
詳しい説明とコード例については、各リファレンスファイルをお読みください。
- セクションの定義 - カテゴリー構成と影響レベル
- ルールのテンプレート - 新しいルールを追加するためのテンプレート
リファレンスファイル
| ファイル | 説明 |
|---|---|
| references/_sections.md | カテゴリーの定義と順序 |
| assets/templates/_template.md | 新しいルール用のテンプレート |
| metadata.json | バージョンとリファレンス情報 |