ksk-design-system 2.8.1 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/ksk-design-system/SKILL.md +153 -0
- package/.claude/skills/ksk-design-system/references/component-decisions.md +87 -0
- package/.claude/skills/ksk-design-system/references/hig-m3-mapping.md +92 -0
- package/.claude/skills/ksk-design-system/references/prohibited-rationale.md +148 -0
- package/.claude/skills/ksk-design-system/references/tokens-reference.md +79 -0
- package/AGENTS.md +64 -6
- package/CLAUDE.md +64 -6
- package/DESIGN.md +24 -1
- package/MIGRATION.md +12 -0
- package/README.md +91 -0
- package/RELEASE.md +13 -0
- package/bin/ds-shape-override.js +149 -0
- package/bin/lint.js +68 -26
- package/bin/overlay-footer-padding.js +129 -0
- package/bin/unlayered-global-override.js +96 -0
- package/contracts/components.json +166 -33
- package/contracts/consumer-requests.json +6 -1
- package/contracts/product-theme-overrides.json +4 -0
- package/contracts/rules.json +40 -4
- package/contracts/token-hex-cache.json +28 -3
- package/dist/class-names.js +1 -1
- package/dist/index.js +2656 -2284
- package/dist/native/ui.js +64 -28
- package/dist/{native-_H0V_r0X.js → native-BQg-H087.js} +162 -42
- package/dist/native.js +1 -1
- package/dist/{server-variants-DTpkG8A7.js → server-variants-C7GNdOYi.js} +28 -3
- package/dist/types/components/patterns/admin/bulk-actions.d.ts +3 -1
- package/dist/types/components/patterns/admin/data-table.d.ts +4 -2
- package/dist/types/components/patterns/chip.d.ts +1 -1
- package/dist/types/components/patterns/commerce/bottom-tab-bar.d.ts +4 -1
- package/dist/types/components/patterns/commerce/price-display.d.ts +1 -1
- package/dist/types/components/patterns/confirm-dialog.d.ts +43 -3
- package/dist/types/components/patterns/responsive-overlay-frame.d.ts +11 -1
- package/dist/types/components/patterns/sidebar-nav.d.ts +88 -0
- package/dist/types/components/patterns/tag.d.ts +1 -1
- package/dist/types/components/ui/accordion.d.ts +12 -3
- package/dist/types/components/ui/alert-dialog.d.ts +3 -1
- package/dist/types/components/ui/badge.d.ts +1 -1
- package/dist/types/components/ui/breadcrumb.d.ts +11 -1
- package/dist/types/components/ui/button.d.ts +36 -1
- package/dist/types/components/ui/card.d.ts +1 -1
- package/dist/types/components/ui/checkbox-card.d.ts +1 -1
- package/dist/types/components/ui/combobox.d.ts +7 -1
- package/dist/types/components/ui/container.d.ts +1 -1
- package/dist/types/components/ui/dialog.d.ts +27 -2
- package/dist/types/components/ui/error-boundary.d.ts +7 -0
- package/dist/types/components/ui/multi-select.d.ts +7 -1
- package/dist/types/components/ui/navigation-bar.d.ts +10 -2
- package/dist/types/components/ui/number-input.d.ts +2 -2
- package/dist/types/components/ui/pagination.d.ts +12 -0
- package/dist/types/components/ui/responsive-dialog.d.ts +1 -1
- package/dist/types/components/ui/section.d.ts +1 -1
- package/dist/types/components/ui/select.d.ts +9 -3
- package/dist/types/components/ui/sheet.d.ts +11 -1
- package/dist/types/components/ui/skeleton.d.ts +3 -1
- package/dist/types/components/ui/slider.d.ts +7 -1
- package/dist/types/components/ui/tabs.d.ts +6 -0
- package/dist/types/components/ui/toast.d.ts +5 -2
- package/dist/types/index.d.ts +6 -3
- package/dist/types/lib/active-element.d.ts +2 -0
- package/dist/types/lib/server-variants/button-variants.d.ts +2 -20
- package/dist/types/lib/server-variants/unstyled.d.ts +1 -1
- package/dist/types/native/components/Alert.d.ts +13 -1
- package/dist/types/native/components/ErrorBoundary.d.ts +3 -0
- package/dist/types/native/components/PillToggle.d.ts +7 -0
- package/dist/types/native/components/ResponsiveDialog.d.ts +6 -1
- package/dist/types/tokens/native/themes.d.ts +132 -12
- package/package.json +11 -5
- package/src/components/COMPONENT_LOOKUP.md +17 -16
- package/src/preset-core.css +9 -0
- package/src/styles/semantic.css +72 -2
- package/src/styles/source-safelist.css +53 -12
- package/templates/AGENTS.md +2 -2
- package/templates/CLAUDE.md +2 -2
- package/tokens.json +50 -7
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ksk-design-system
|
|
3
|
+
description: KSK Design System で UI を実装・修正・レビューするとき必ず適用する判断ルール。トークン設計(semantic のみ・生値禁止)・禁止パターン(正本: rules.json)・HIG/M3 基準・コンポーネント選択の判断基準を定義する。React + Tailwind v4 + TypeScript の UI コードを書く前に読むこと。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# KSK Design System — 判断Skill
|
|
7
|
+
|
|
8
|
+
KSK は Brand 色10行の差し替えで全コンポーネントが切り替わるマルチテーマ DS。
|
|
9
|
+
全ルールは「テーマ切替・ダークモード・消費側の色文脈のどれかで壊れる書き方を排除する」ために存在する。
|
|
10
|
+
|
|
11
|
+
## 0. 正本の読み順(このSkillは索引。複製ではない)
|
|
12
|
+
|
|
13
|
+
実データは必ず正本を読む。Skill と正本が食い違ったら**正本が勝つ**。
|
|
14
|
+
|
|
15
|
+
1. `src/components/COMPONENT_LOOKUP.md` — 既存コンポーネントの索引。**UI を書く前に必ず確認**
|
|
16
|
+
2. `contracts/rules.json` — 禁止パターン+AIアンチパターンの正規表現つき正本
|
|
17
|
+
3. `tokens.json` / `src/preset.css` — トークン値の正本
|
|
18
|
+
4. `contracts/components.json` — variant・使用ルールの正本
|
|
19
|
+
5. 画面(ページ/ダイアログ等)を実装する場合は `contracts/screen-patterns.json`(どのシェル/パターンを使うか、decisionTree)と `contracts/composition.json`(内部の並べ方)
|
|
20
|
+
|
|
21
|
+
コンポーネントの **props の正確な形は推測しない**。使う直前に `contracts/components.json` か
|
|
22
|
+
該当コンポーネントの `.tsx`(COMPONENT_LOOKUP.md の import パス先)を読んで確認する。
|
|
23
|
+
|
|
24
|
+
## 1. 絶対原則(5つ。違反は書き直し)
|
|
25
|
+
|
|
26
|
+
### 原則1: 色はセマンティックトークンのみ
|
|
27
|
+
生 `#hex`・Tailwind 標準色・`--Primitive-*` 直参照は、Brand 差し替えとダーク反転の両方から取り残される。
|
|
28
|
+
- 良い例: `bg-[var(--Surface-Primary)] text-[var(--Text-High-Emphasis)]`
|
|
29
|
+
- **絶対やるな**: `bg-blue-500`, `text-white`, `#3B82F6`, `var(--Primitive-Brand-500)`
|
|
30
|
+
|
|
31
|
+
### 原則2: DS コンポーネントを使う(生タグ・再実装禁止)
|
|
32
|
+
生タグはフォーカスリング・44px ターゲット・aria を持たない。合成パターン(sheet 骨組み・設定行・toggle 等)も DS にある。
|
|
33
|
+
- 良い例: `<Button variant="secondary" size="sm">` / `<Select><SelectItem>`
|
|
34
|
+
- **絶対やるな**: `<button>`, `<a href>`, `<div onClick>`, `div.fixed.inset-0` 自作モーダル, Button 並べた自作トグル
|
|
35
|
+
|
|
36
|
+
### 原則3: 文脈非依存 — 色を継承に任せない
|
|
37
|
+
Tailwind v4 は border/ring/outline の既定が currentColor。消費側が濃色テキストを敷くと無指定の枠線・文字が化ける(実害あり)。テキスト要素に `text-[var(--Text-*)]`、サーフェスに `bg-[var(--Surface-*)]` を明示し、**border は必ず色を併記**する。
|
|
38
|
+
- 良い例: `border border-[var(--Border-Low-Emphasis)]`。状態切替は `border-transparent` + `data-[state=active]:border-[var(--Brand-Primary)]` のペア
|
|
39
|
+
- **絶対やるな**: 色なしの `border` 単独、bg 未指定のカード/ポップオーバー(親の背景が透ける)
|
|
40
|
+
|
|
41
|
+
### 原則4: タイポは typo-* クラスのみ
|
|
42
|
+
size/weight/line-height/tracking は typo-* に内包済み(和文最適化)。個別指定は行間バラバラと日本語可読性低下を招く。色だけ別指定する。
|
|
43
|
+
- 良い例: `className="typo-body-sm text-[var(--Text-Low-Emphasis)]"`
|
|
44
|
+
- **絶対やるな**: `text-sm font-bold`, `text-[14px]`, `tracking-tight`。本文に typo-body-xs(12px)/caption(11px)(本文の下限は typo-body-sm=14px)
|
|
45
|
+
|
|
46
|
+
### 原則5: アイコンは iconsax-reactjs のみ
|
|
47
|
+
DS 全体でアイコンの線幅・スタイルを統一するため。
|
|
48
|
+
- 良い例: `import { Add } from "iconsax-reactjs"`
|
|
49
|
+
- **絶対やるな**: `lucide-react`, `heroicons`, インライン SVG の手書きアイコン
|
|
50
|
+
|
|
51
|
+
## 2. 検証可能ルール(クラス設計)
|
|
52
|
+
|
|
53
|
+
各行は grep で機械検証できる形で守ること。
|
|
54
|
+
|
|
55
|
+
- **gap を使う**: 兄弟間の間隔は flex/grid + `gap-*`。`space-x-*`/`space-y-*` は使わない(divider や条件レンダリングで余白が壊れ、gap と混在すると余白が二重になる)。
|
|
56
|
+
良い例: `<div className="flex flex-col gap-2">` / 絶対やるな: `space-y-2`
|
|
57
|
+
- **正方形は size-***: 幅=高さの要素は `size-*` 1つで書く。`w-* h-*` 併記は片方だけ変更されて歪む事故の元。
|
|
58
|
+
良い例: `size-10` / 絶対やるな: `w-10 h-10`
|
|
59
|
+
- **className 合成は cn()**: 条件付き・props 併合は必ず `cn()`(`@/lib/utils`)。テンプレートリテラル連結は Tailwind の競合解決がされず false が文字列化する。
|
|
60
|
+
良い例: `cn("flex gap-2", isActive && "bg-[var(--Surface-Accent-Primary-Light)]", className)` / 絶対やるな: `` className={`flex ${extra}`} ``
|
|
61
|
+
- **variant/size prop 優先**: 見た目の変更はまず variant・size の語彙で表現し、className 上書きは DS に語彙が無いときの最終手段(上書きが2回続いたら variant 追加を検討・提案する)。
|
|
62
|
+
良い例: `<Button variant="destructive" size="sm">` / 絶対やるな: `<Button className="bg-red-500 h-8">`
|
|
63
|
+
- **スペーシングは 4px グリッド**: Tailwind 標準クラスの**整数ステップのみ**(高頻度は gap/p 1–6)。任意値 `p-[17px]` に加え、小数ステップ `gap-1.5`/`p-2.5`(6px/10px = グリッド外)も禁止。
|
|
64
|
+
良い例: `gap-2`(8px) / 絶対やるな: `gap-1.5`, `p-[10px]`
|
|
65
|
+
- **角丸の使い分け**: 面/モーダル/シートは意味トークン `rounded-[var(--Radius-Surface|Modal|Sheet)]`(14/24/32px)。その他の小要素は `rounded-{none|sm|md|lg|xl|2xl|full}` の7値のみ。Button/Chip/Badge はピル(full)。
|
|
66
|
+
- **影は5段のみ**: `shadow-[var(--shadow-sm|md|lg|dialog|tooltip)]`。Tailwind 標準 shadow 禁止。境界は「影+1px罫線」で表現。
|
|
67
|
+
- **motion は 150/200ms ease-out**(sheet は 280ms spring)。300ms 以上禁止。常時ループアニメはローディング限定。
|
|
68
|
+
- **ベンダープレフィックスは `-webkit-` を先、標準形を後**(逆順だと消費側 minifier の dedupe で Firefox で静かに無効化)。
|
|
69
|
+
|
|
70
|
+
## 3. 禁止パターン Top10(全件は rules.json、rationale は references/)
|
|
71
|
+
|
|
72
|
+
| # | 禁止 | なぜ |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| P008/P009 | 生 hex・Tailwind 標準色 | テーマ切替・dark で死ぬ |
|
|
75
|
+
| P015 | Primitive 直参照 | hover/active の段階設計(600/700/800)を破壊 |
|
|
76
|
+
| P032 | 色なし border | v4 の currentColor 既定で黒ずむ(実害あり) |
|
|
77
|
+
| P007 | 自作モーダル | フォーカストラップ・ESC・aria が全欠落 |
|
|
78
|
+
| P011/P016 | フォント直書き | 行間・weight の設計が画面ごとに割れる |
|
|
79
|
+
| P012 | 任意値スペーシング | 4px グリッドのリズム崩壊 |
|
|
80
|
+
| P013/P021 | カラーバー・グラデーション | AI 生成の定番。DS の視覚言語と異質 |
|
|
81
|
+
| P023 | outline-none | キーボード利用者の現在地を消す a11y 違反(outline-hidden で強制配色モードにも対応) |
|
|
82
|
+
| P026 | placeholder のみ | SR が読まない・入力中に説明が消える |
|
|
83
|
+
| P033–P043 | 合成パターンの再実装 | 亜種が増え一括修正が効かなくなる。例外は `ksk-ds-allow-custom-ui` コメント必須 |
|
|
84
|
+
|
|
85
|
+
## 4. HIG/M3 チェックリスト(衝突時は厳しい方)
|
|
86
|
+
|
|
87
|
+
実装後、以下を Yes/No で点検する:
|
|
88
|
+
|
|
89
|
+
- [ ] タッチターゲット: 操作要素の実効ヒット領域 ≥44px(推奨48px)。チップは hitSlop で実効44px
|
|
90
|
+
- [ ] フォーカスリング: 全操作要素に `focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50`
|
|
91
|
+
- [ ] モーダリティ: 作業面=Dialog / 割り込み確認=AlertDialog・ConfirmDialog(外タップで閉じない)/ 軽い補助=Sheet。確認を素の Dialog で組んでいないか
|
|
92
|
+
- [ ] elevation: 影が5段トークンに収まり「浮く高さと影の強さ」が対応しているか(Card=md、Popover=lg、Dialog=dialog)
|
|
93
|
+
- [ ] コントラスト: 通常文字 ≥4.5:1、UI 要素 ≥3:1。状態表現は色+アイコン+テキストの3点セット
|
|
94
|
+
- [ ] `<img>` に alt、アイコンボタンに aria-label、入力に `<Label>`
|
|
95
|
+
- [ ] `prefers-reduced-motion` を壊す常時アニメが無い
|
|
96
|
+
|
|
97
|
+
## 5. 実装後の機械検証(必須)
|
|
98
|
+
|
|
99
|
+
作業場所で手順が違う。**consumer で `bash scripts/...` や `npm run check` は動かない**(DS リポジトリにしか無い)。
|
|
100
|
+
|
|
101
|
+
### consumer アプリで UI を書いたとき
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx ksk-ds lint src # DS-first ルール違反(rules.json)を検査。毎回
|
|
105
|
+
npx ksk-ds lint --changed # 差分だけ検査(編集の都度はこちらが速い)
|
|
106
|
+
npx ksk-ds check-duplicates src --strict # DS と同名のローカル実装を検査(CI 向け。検出時 exit 1)
|
|
107
|
+
npx ksk-ds check-migration ./src # 非推奨 API の残存を検査(read-only)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Storybook がある consumer は、ツールバーの **Hostile ctx** を loud にしてマゼンタ化・背景透け(文脈非依存違反)が無いか目視確認。
|
|
111
|
+
DS に無い部品が要るときは、consumer 側に別台帳を作らず DS へ issue を出す(CLAUDE.md の「ローカル二重実装ゲート」)。
|
|
112
|
+
|
|
113
|
+
### DS リポジトリの中で作業するとき
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
bash scripts/lint-scratch.sh # .tsx を編集したら毎回
|
|
117
|
+
npm run check # コンポーネント増減時(tsc+lint+drift+lookup)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Storybook ツールバーの **Hostile ctx** を loud にして、マゼンタ化・背景透け(文脈非依存違反)が無いか目視確認。
|
|
121
|
+
|
|
122
|
+
**コンポーネントを増減したら**(DS リポジトリ内)、コードだけでは完了しない。次の連鎖を全部更新する:
|
|
123
|
+
`src/index.ts` → `contracts/components.json`(定義+`meta.counts`)→ `.stories.tsx` →
|
|
124
|
+
`npm run generate:lookup` → `bash scripts/check-drift.sh`(一括なら `npm run check`)。
|
|
125
|
+
contracts と実装の drift は静かに壊れるため、レビューでは counts 差分も見る。
|
|
126
|
+
|
|
127
|
+
## 5.5 レビュー手順(PR / 差分を見る順)
|
|
128
|
+
|
|
129
|
+
壊れ方が深刻な順に見る:
|
|
130
|
+
|
|
131
|
+
1. **テーマ切替で壊れないか**(error 級): 生 hex / Tailwind 標準色 / `--Primitive-*` 直参照 / `text-white`。4テーマ全部で成立するか
|
|
132
|
+
2. **消費側文脈で壊れないか**(error 級): 無色 border・継承依存・bg 未指定サーフェス。「Storybook では正しく見える」は合格条件でない
|
|
133
|
+
3. **a11y**: フォーカスリング削除・`<div onClick>`・aria-label なし icon button・placeholder のみ・色のみのステータス区別
|
|
134
|
+
4. **DS スケール逸脱**(warning 級): 角丸・shadow・spacing の許可セット外、300ms 超アニメ
|
|
135
|
+
5. **ライティング**: §7 参照
|
|
136
|
+
|
|
137
|
+
**severity の読み方**: rules.json の `error` は無条件で直す。`warning` は「消費側テーマ・日本語文脈で壊れる可能性」の警告 — 直さない場合は理由を PR に書く。
|
|
138
|
+
|
|
139
|
+
**例外の作法**: 禁止パターンを意図的に破る正当な理由がある場合のみ `// ksk-ds-allow-custom-ui: <理由>` を該当行近くに残す。理由なしの suppress は差し戻し対象。
|
|
140
|
+
|
|
141
|
+
## 6. references/ の分岐
|
|
142
|
+
|
|
143
|
+
| 状況 | 読む |
|
|
144
|
+
|---|---|
|
|
145
|
+
| 禁止パターンに引っかかった・例外を検討したい | `references/prohibited-rationale.md`(全件の why) |
|
|
146
|
+
| トークン名がわからない・色/typo/spacing の選択に迷う | `references/tokens-reference.md` |
|
|
147
|
+
| どのコンポーネントを使うか迷う(モーダル/通知/切替/フォーム) | `references/component-decisions.md` |
|
|
148
|
+
| タッチターゲット・elevation・motion・type scale の根拠が必要 | `references/hig-m3-mapping.md` |
|
|
149
|
+
|
|
150
|
+
## 7. ライティング(UI コピー)
|
|
151
|
+
|
|
152
|
+
日本語・敬体・簡潔。和文全角/欧文半角、見出しに「。」なし、日付 YYYY/M/D、
|
|
153
|
+
ボタンは動詞(「保存する」)、エラーは次の行動を明示。正本: `contracts/rules.json` の `writing`。
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# コンポーネント選択の判断樹
|
|
2
|
+
|
|
3
|
+
> 一覧と import パスの正本は `src/components/COMPONENT_LOOKUP.md`(自動生成・132個)、
|
|
4
|
+
> variant と使用ルールの正本は `contracts/components.json`。本ファイルは
|
|
5
|
+
> 「どれを使うか」を最短で決めるための判断樹。
|
|
6
|
+
|
|
7
|
+
## 大原則
|
|
8
|
+
|
|
9
|
+
1. UI を書く前に COMPONENT_LOOKUP.md で同等品を探す。**あれば必ず使う(再実装禁止)**
|
|
10
|
+
2. 見つからない場合のみ組む。合成パターン(sheet 骨組み・設定行・file picker 等)にも
|
|
11
|
+
DS 部品があるので P033–P043 を確認してから
|
|
12
|
+
3. どうしても例外が要るときは `ksk-ds-allow-custom-ui` コメントで理由を残す
|
|
13
|
+
|
|
14
|
+
## オーバーレイ系 — 何を出すか
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
ユーザーを「止めて」確認させたい(削除・送信・不可逆)?
|
|
18
|
+
├─ Yes → ConfirmDialog(定型: 非同期onConfirm・loading込み)
|
|
19
|
+
│ もっと自由な構成が要るなら AlertDialog(role=alertdialog・外タップで閉じない)
|
|
20
|
+
│ 破壊的 CTA は variant="destructive"、Cancel は tertiary
|
|
21
|
+
└─ No → その面で「作業」させる(フォーム・絞り込み)?
|
|
22
|
+
├─ Yes → Dialog(中央・24px角丸)。PC/SP 両対応なら ResponsiveDialog(PC=Dialog/SP=Sheet 自動)
|
|
23
|
+
└─ No → 軽い補助・メニュー・フィルター?
|
|
24
|
+
├─ 画面端から → Sheet(side=bottom でボトムシート。swipeToClose は bottom 系のみ)
|
|
25
|
+
├─ 要素の近くに小さく・操作あり → Popover(shadow-lg)
|
|
26
|
+
├─ 短文の補足のみ・操作なし → Tooltip(shadow-tooltip)
|
|
27
|
+
└─ リッチなプレビュー(hover) → HoverCard
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**禁止**: 確認フローを素の Dialog で組む(ConfirmDialog を使う)。div.fixed.inset-0 自作(P007)。
|
|
31
|
+
|
|
32
|
+
### Sheet の組み立て(モバイル detail/edit/form)
|
|
33
|
+
|
|
34
|
+
- 外枠 class recipe を手書きしない → `BottomSheetFrame preset="mobile-full|mobile-form|desktop-floating"`(P042)
|
|
35
|
+
- ヘッダ+ケバブ → `DetailSheetScaffold` / `DetailSheetHeader trailing={<KebabMenu/>}`(P037)
|
|
36
|
+
- フッター CTA のキーボード/safe-area 対応 → `KeyboardAwareSheetFooter`
|
|
37
|
+
- フォーム入力主体のシート → `BottomSheetForm`。detail/edit は `autoFocus={false}`
|
|
38
|
+
|
|
39
|
+
## フィードバック系 — どう知らせるか
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
一時的な操作結果(保存した・復旧した・失敗した)?
|
|
43
|
+
├─ Yes → toast.*(toast.success / connectionRestored / retryStarted / retryFailed)… P034
|
|
44
|
+
└─ No(持続する状態・画面に残る情報)→
|
|
45
|
+
├─ ページ/セクション頭のお知らせ → Banner または Alert(bordered=白背景+枠 / inline=色背景コンパクト)
|
|
46
|
+
├─ データがゼロ → EmptyState(actionLabel + actionLayout。CTA の className 手組み禁止 P036)
|
|
47
|
+
├─ 読み込み中 → Skeleton(構造が既知)/ Progress・ProgressRing(進捗既知)
|
|
48
|
+
└─ 要素に付く状態 → Badge(variant: success/warning/info/destructive...)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
状態表現は常に**色+アイコン+テキスト**(A008/A009。色だけで区別しない)。
|
|
52
|
+
|
|
53
|
+
## 選択・切替系
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
選択肢の数と性質は?
|
|
57
|
+
├─ 2–4択のビュー切替(フィルタ的) → PillToggle
|
|
58
|
+
├─ 5択以上のビュー切替 → Tabs(ステータス別一覧なら StatusTabs)
|
|
59
|
+
├─ 単一選択(フォーム値) → RadioGroup / 説明付きカードなら CheckboxCardGroup 系
|
|
60
|
+
├─ 複数選択 → CheckboxGroup / MultiSelect(多数から検索選択)
|
|
61
|
+
├─ On/Off → Switch
|
|
62
|
+
└─ 一覧から1つ選ぶ(入力欄形式) → Select / 検索付きなら Combobox
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**禁止**: Button を並べて aria-pressed で自作 toggle(P033)。
|
|
66
|
+
|
|
67
|
+
## フォーム系
|
|
68
|
+
|
|
69
|
+
- 必ず `<Label>` とセット(P026)。定型は `FormField` / `Form` 一式
|
|
70
|
+
- テキスト → Input / 複数行 → Textarea / 自動伸長 → AutoGrowTextarea
|
|
71
|
+
- 数値 → NumberInput / 日付 → DateField・DatePicker / ファイル → CompactFilePicker・ImageAttachmentPicker(P039)
|
|
72
|
+
- メールは type="email"(P027)
|
|
73
|
+
|
|
74
|
+
## ナビゲーション・シェル
|
|
75
|
+
|
|
76
|
+
- 画面上部バー → NavigationBar / パンくず → Breadcrumb / ページ送り → Pagination
|
|
77
|
+
- モバイル下部ナビ・FAB → MobileAppShell + BottomTabBar + MobileFloatingActionButton(P041。手書き geometry 禁止)
|
|
78
|
+
- サイドメニュー → MenuDrawer / 設定画面 → SettingsSection + SettingsListRow(P038)
|
|
79
|
+
- Expo Router の tabBar → createExpoRouterTabBar / LiquidBottomTabBar(P043)
|
|
80
|
+
|
|
81
|
+
## Button variant の選び方(contracts/components.json より)
|
|
82
|
+
|
|
83
|
+
- 主要 CTA → `default` / 第2アクション → `secondary` / 控えめ → `tertiary`・`ghost`
|
|
84
|
+
- 破壊的 → `destructive` / リンク見た目 → `link`
|
|
85
|
+
- グラデーション・写真背景上のみ → `glass`(暗い媒体上は `glass-inverse`、FAB は `glass-accent`)
|
|
86
|
+
- 暗背景・ヒーロー専用 → `inverse` / `ghost-inverse`、hero CTA は size="hero"(56px ピル)
|
|
87
|
+
- アイコン単独 → size="icon|icon-sm|icon-lg|icon-xl" + **aria-label 必須**
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# HIG × M3 × KSK トークン対応表
|
|
2
|
+
|
|
3
|
+
> KSK の設計基準は Apple HIG と Material Design 3。**衝突時は厳しい方を採用**する
|
|
4
|
+
> (例: タッチターゲットは min 44 かつ推奨 48 の両立)。本ファイルは KSK トークンが
|
|
5
|
+
> HIG/M3 のどの規範に対応するかの参照。値の正本は `tokens.json` / `src/preset.css`。
|
|
6
|
+
|
|
7
|
+
## タッチターゲット
|
|
8
|
+
|
|
9
|
+
| 対象 | HIG (iOS) | M3 (Android) | KSK 採用値(厳しい方合成) |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| ボタン / アイコンボタン / 入力 / ナビ項目 | ≥44×44pt | ≥48×48dp | **min 44px・推奨 48px**(`touchTargets`) |
|
|
12
|
+
| チップ(視覚 32–36px が避けられない場合) | — | — | **hitSlop で実効 44px を確保** |
|
|
13
|
+
|
|
14
|
+
チェック方法: レンダリング後の実効ヒット領域(visible + hitSlop)が 44px 未満なら違反。
|
|
15
|
+
`Button size="icon-xl"` が HIG 最小 44px に対応。
|
|
16
|
+
|
|
17
|
+
## タイポグラフィ(ロールマッピング)
|
|
18
|
+
|
|
19
|
+
KSK の `typo-*` ユーティリティは HIG Text Styles / M3 Type Scale のロールに対応する。
|
|
20
|
+
**和文最適化のため値は独自**(line-height 1.5–1.75、見出し +0.04em、`tracking-tight` 禁止)。
|
|
21
|
+
|
|
22
|
+
| KSK | HIG 相当 | M3 相当 | 用途 |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| typo-display-xl/lg (48/36px) | Large Title+ | Display L/M | ヒーロー・LP |
|
|
25
|
+
| typo-heading-3xl/2xl (28/24px) | Title 1/2 | Headline L/M | ページ・主要セクション |
|
|
26
|
+
| typo-heading-xl/lg (21/18px) | Title 3 / Headline | Headline S / Title L | サブセクション・グループ |
|
|
27
|
+
| typo-heading-md/sm (16/14px) | Headline / Subheadline | Title M/S | 小見出し・ラベル的見出し |
|
|
28
|
+
| typo-body-lg/md (16/14px) | Body / Callout | Body L/M | 本文 |
|
|
29
|
+
| typo-body-sm (12px) | Footnote | Body S | 補足。**本文の下限は 12px** |
|
|
30
|
+
| typo-body-xs (10px) | Caption 2 | — | 補助ラベル専用・**本文禁止** |
|
|
31
|
+
| typo-label-lg/md (16/14px) | — (button) | Label L | ボタン・ナビ |
|
|
32
|
+
| typo-label-sm/xs (12/10px) | — | Label M/S | タグ・バッジ |
|
|
33
|
+
| typo-caption (11px) | Caption 1 | — | 注釈・法的表記のみ |
|
|
34
|
+
|
|
35
|
+
M3 デフォルト(Roboto 前提の tracking)は和文に適用しない。HIG の Dynamic Type 対応は
|
|
36
|
+
Web では必須にしないが、`rem` ベース禁止はしていない(px 指定は typo-* 内に隠蔽)。
|
|
37
|
+
|
|
38
|
+
## Elevation(M3 levels → KSK 5段)
|
|
39
|
+
|
|
40
|
+
M3 の elevation level 0–5 を KSK は**セマンティック5段のみ**に絞る。
|
|
41
|
+
tonal elevation(M3 の色による高度表現)は不採用で、**影+1px罫線**が KSK の境界言語。
|
|
42
|
+
|
|
43
|
+
| KSK トークン | M3 相当 | 用途(これ以外に使わない) |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| (影なし+罫線) | Level 0 | 既定の面・リスト |
|
|
46
|
+
| `--shadow-sm` | Level 1 | 微細な浮き |
|
|
47
|
+
| `--shadow-md` | Level 1–2 | Card・標準の面 |
|
|
48
|
+
| `--shadow-lg` | Level 2–3 | Dropdown・Popover(浮く要素) |
|
|
49
|
+
| `--shadow-dialog` | Level 3–5 | Dialog・Modal |
|
|
50
|
+
| `--shadow-tooltip` | — | Tooltip 専用 |
|
|
51
|
+
|
|
52
|
+
チェック方法: `shadow-xl` 等の Tailwind 標準や、Card に `--shadow-dialog` を使うのは違反。
|
|
53
|
+
「1段浮くごとに1段強い影」の対応から外れていないか確認する。
|
|
54
|
+
|
|
55
|
+
## Shape(M3 shape scale / HIG concentricity → KSK 角丸階層)
|
|
56
|
+
|
|
57
|
+
丸さは**階層=面 < モーダル < シート**で意味を持つ(HIG の同心円的角丸・M3 shape scale の思想)。
|
|
58
|
+
|
|
59
|
+
| KSK | 値 | M3 shape 相当 |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `--Radius-Surface`(Card/Popover パネル) | 14px | Small/Medium |
|
|
62
|
+
| `--Radius-Modal`(中央 Dialog/AlertDialog) | 24px | Extra Large |
|
|
63
|
+
| `--Radius-Sheet`(bottom/float Sheet) | 32px | Extra Large+ |
|
|
64
|
+
| `rounded-full`(Button/Chip/Badge/Avatar) | 9999px | Full(ピル) |
|
|
65
|
+
| 素の rounded-*(その他の小要素) | none/4/6/8/12/16 | Extra Small〜Large |
|
|
66
|
+
|
|
67
|
+
## Motion
|
|
68
|
+
|
|
69
|
+
HIG「素早く控えめ」× M3 duration/easing token の交差を 3 値に集約。バウンド禁止。
|
|
70
|
+
|
|
71
|
+
| KSK | 値 | 根拠 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| micro | 150ms ease-out | M3 short (50–200ms) / HIG の即時フィードバック |
|
|
74
|
+
| enter | 200ms ease-out | M3 medium 下限。300ms 以上は P030 で禁止 |
|
|
75
|
+
| sheetSpring | 280ms cubic-bezier(0.32,0.72,0,1) | iOS シートのスプリング近似(HIG 由来) |
|
|
76
|
+
|
|
77
|
+
`prefers-reduced-motion` を尊重する(HIG/M3/WCAG 共通要件)。
|
|
78
|
+
|
|
79
|
+
## モーダリティ(HIG Modality / M3 Dialogs の使い分け)
|
|
80
|
+
|
|
81
|
+
| 状況 | 使うもの | 根拠 |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| 作業面(フォーム・絞り込み) | `Dialog`(role=dialog、24px 角丸) | HIG: モーダルは自己完結タスク |
|
|
84
|
+
| 割り込み確認(削除等の不可逆) | `AlertDialog`/`ConfirmDialog`(role=alertdialog、外タップで閉じない) | HIG Alerts / M3 basic dialog: 明示的に選ばせる |
|
|
85
|
+
| 補助・フィルター・メニュー(軽い文脈) | `Sheet`(bottom で BottomSheet) | HIG Sheets / M3 bottom sheets |
|
|
86
|
+
| PC=Dialog / モバイル=Sheet の自動切替 | `ResponsiveDialog` | プラットフォーム適応(HIG/M3 双方の作法) |
|
|
87
|
+
|
|
88
|
+
## コントラスト(WCAG 2.1 AA — HIG/M3 共通の下限)
|
|
89
|
+
|
|
90
|
+
- 通常テキスト ≥4.5:1 / 大テキスト(18px+ bold)≥3:1 / UI 要素・アイコン ≥3:1
|
|
91
|
+
- ステータス・エラーは**色+アイコン+テキストの3点セット**(色のみ禁止)
|
|
92
|
+
- Categorical 色の文字は必ず `-Bold` tier(base は白背景で 3:1 未満になりうる)
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# 禁止パターン+AIアンチパターン(正本: rules.json)— なぜ禁止か
|
|
2
|
+
|
|
3
|
+
> 正規表現・excludes の正本は `contracts/rules.json`。本ファイルは各ルールの
|
|
4
|
+
> **rationale(防ぐ失敗)** を言語化した参照資料。ID は rules.json と対応。
|
|
5
|
+
|
|
6
|
+
## appliesTo — ルールの適用範囲(capability タグ)
|
|
7
|
+
|
|
8
|
+
各ルールは `appliesTo` で適用範囲を絞れる(issue #391)。**未指定は全ファイル対象**
|
|
9
|
+
(後方互換)で、指定した場合は列挙のうち 1 つでも一致すれば適用する。
|
|
10
|
+
|
|
11
|
+
値は「プラットフォーム」ではなく **capability(そのファイルがどの記法を持ちうるか)**:
|
|
12
|
+
|
|
13
|
+
| タグ | 意味 | 付けるルール |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `dom` | 小文字の HTML 生タグ・`href` / `type` 等の DOM 属性が書ける | P001–P007, P024, P025, P027, P039, P045, P051, AI8 |
|
|
16
|
+
| `tailwind` | `className` に Tailwind クラスを書く(web + **NativeWind** の RN) | P009–P013, P016–P023, P028–P032, P041, P042, P044, P046, P048, P052, AI1–AI6, AI9 |
|
|
17
|
+
| `web` | CSS 変数・CSS 単位が効く純 web | P015, AI7 |
|
|
18
|
+
| `native` | React Native のファイル | (現時点で専用ルールなし) |
|
|
19
|
+
|
|
20
|
+
`"*.css"` のようなグロブも書ける(P049 / P053 が使用)。旧語彙の `"web"` / `"native"` も
|
|
21
|
+
capability として引き続き解釈される。
|
|
22
|
+
|
|
23
|
+
### なぜ platform 二値ではないのか
|
|
24
|
+
|
|
25
|
+
最初は `["web"]` / `["native"]` の二値で棚卸ししたが、**consumer の多く(資格系の Web アプリ群)は
|
|
26
|
+
NativeWind を使っており、RN でも `className` に Tailwind クラスを書く**。
|
|
27
|
+
「RN だから Tailwind 系は全部外す」と倒すと、そちらの lint がほぼ無効化される
|
|
28
|
+
(ある consumer アプリの実測で 858 件 → 66 件、92% 減)。
|
|
29
|
+
一方 StyleSheet 系の RN consumerでは Tailwind 系は誤検知しかしない
|
|
30
|
+
(P032 は 76 件全部が `borderColor: colors.border` の `.border` への誤爆だった)。
|
|
31
|
+
この 2 つを両立させるには、ファイル側を `className` の有無で見分ける必要がある。
|
|
32
|
+
|
|
33
|
+
ファイルの capability:
|
|
34
|
+
|
|
35
|
+
- web(native シグナルなし)→ `{dom, tailwind, web}`
|
|
36
|
+
- native + `className` あり → `{native, tailwind}`
|
|
37
|
+
- native + `className` なし → `{native}`
|
|
38
|
+
|
|
39
|
+
native の判定シグナルは `*.native.tsx` / `react-native` の **import 文** /
|
|
40
|
+
`ksk-design-system/native` の import 文 / `StyleSheet.create`。
|
|
41
|
+
文字列の中に import 文の見本があるだけのファイルを native 扱いしないよう、
|
|
42
|
+
シグナルは行頭アンカー付きの構文形に限定している。
|
|
43
|
+
CLI の `--platform web|native` がファイル判定より優先されるが、
|
|
44
|
+
`--platform native` でも tailwind を持つかどうかはソースの `className` 有無で決める。
|
|
45
|
+
|
|
46
|
+
### typo は fail-open
|
|
47
|
+
|
|
48
|
+
`appliesTo` に capability でもグロブでもない値(typo)が 1 つでもあると、そのルールは
|
|
49
|
+
**全ファイル対象へ倒れ**、実行ごとに 1 回 stderr へ警告が出る。閉じる側に倒すと
|
|
50
|
+
typo したルールがどのファイルにも当たらないまま静かに無効化されるため。
|
|
51
|
+
|
|
52
|
+
### 付け方の原則
|
|
53
|
+
|
|
54
|
+
`#hex` 直書き(P008)や DS コンポーネントの再実装禁止(P033–P040 等)は記法非依存なので
|
|
55
|
+
`appliesTo` を付けず全対象のままにする。**迷ったら付けない。**
|
|
56
|
+
web 前提の fix 文言が native で実行不能なルールは `fixNative` を持たせる
|
|
57
|
+
(P008: `var(--...)` → native のトークン)。
|
|
58
|
+
|
|
59
|
+
## component — 生タグ・自作の禁止(P001–P007)
|
|
60
|
+
|
|
61
|
+
すべて同じ失敗を防ぐ: **生タグは DS のトークン・状態・a11y 実装を全部持っていない**。
|
|
62
|
+
生 `<button>` はフォーカスリング・disabled 表現・タッチターゲット 44px を欠き、
|
|
63
|
+
画面ごとに微妙に違うボタンが増殖して DS の意味が消える。
|
|
64
|
+
|
|
65
|
+
- **P001 `<button>`** → `<Button variant size>`。variant/size の語彙で意図が仕様化される
|
|
66
|
+
- **P002 `<input>`** → `<Input>`。高さ48px・border色・focus 実装込み
|
|
67
|
+
- **P003 `<textarea>`** → `<Textarea>`
|
|
68
|
+
- **P004 `<select>`** → `<Select><SelectItem>`。ネイティブ select はスタイル不能でOS毎に見た目が割れる
|
|
69
|
+
- **P005 `<table>`** → `DataTable`。生 table は CLS(レイアウトシフト)とスタイル崩れの実績あり
|
|
70
|
+
- **P006 `<a href>`** → `<Button variant="link">` または `<Button asChild><a>`。リンクの見た目が野良化するのを防ぐ
|
|
71
|
+
- **P007 `div.fixed.inset-0` 自作モーダル** → `<Dialog>`/`<Sheet>`。自作はフォーカストラップ・ESC・スクロールロック・aria が全部欠落する(a11y 事故の定番)
|
|
72
|
+
- **P029 テンプレートリテラルで className 組み立て** → `cn()`/CVA。文字列連結は Tailwind の競合解決がされず、`false`/`undefined` が class 文字列に混入する
|
|
73
|
+
|
|
74
|
+
## color — 生値・非セマンティック色の禁止(P008–P010, P015, P018)
|
|
75
|
+
|
|
76
|
+
すべて同じ失敗を防ぐ: **マルチテーマ DS の生命線はセマンティック層経由**。
|
|
77
|
+
生値は Brand 差し替え(10行)とダークモード反転の両方から取り残される。
|
|
78
|
+
|
|
79
|
+
- **P008 生 `#hex`** → `var(--...)`。テーマ切替・dark 反転に追随しない死に色になる
|
|
80
|
+
- **P009 Tailwind 標準色(`bg-blue-500` 等)** → 同上。しかも「たまたま今のテーマと似た色」が選ばれるため、テーマを替えた瞬間だけ破綻して発見が遅れる
|
|
81
|
+
- **P010 `text-white` / `bg-white`** → `text-[var(--Text-on-Inverse)]` / `bg-[var(--Surface-Primary)]`。dark モードで白背景が残留する典型源
|
|
82
|
+
- **P015 `--Primitive-Brand` 直接使用** <!-- docs-drift-ignore: --Primitive-Brand --> → `var(--Brand-Primary)` 等。Primitive 直参照は「どの shade を使うか」の判断が画面ごとにバラけ、hover/active の段階設計(600/700/800)を破壊する
|
|
83
|
+
- **P018 `text-black`** → `text-[var(--Text-High-Emphasis)]`。純黒 #000 は DS に存在しない(最暗は Gray-900)。dark でも反転しない
|
|
84
|
+
|
|
85
|
+
## typography(P011, P016, P017)
|
|
86
|
+
|
|
87
|
+
- **P011 `text-[14px]` 直書き** → `typo-*`。サイズだけ合わせても line-height/weight/tracking が欠け、行間バラバラの画面になる
|
|
88
|
+
- **P016 `font-bold` 等の直書き** → `typo-*` に weight は内包済み。二重指定は typo クラス側の設計(例: label-sm は 500)と衝突する
|
|
89
|
+
- **P017 `tracking-tight`** → 禁止。英文デザインの真似で日本語に適用すると可読性が著しく落ちる。和文の letter-spacing は typo-* 側で最適化済み(見出し +0.04em)
|
|
90
|
+
|
|
91
|
+
## spacing / layout(P012, P019–P022, P028, P031)
|
|
92
|
+
|
|
93
|
+
- **P012 任意値スペーシング `p-[17px]`** → 4px グリッド外の値は隣接要素とリズムが合わず「1px ズレ」の温床。標準クラスのみ
|
|
94
|
+
- **P019 `rounded-3xl` 等の許可外角丸** → 許可7値(none/sm/md/lg/xl/2xl/full)のみ。場当たりの角丸は面/モーダル/シートの「丸さの階層」(8<24<32)を壊す
|
|
95
|
+
- **P020 Tailwind 標準 shadow(`shadow-md` 等)** → `var(--shadow-*)` 5段のみ。標準 shadow は DS の「影+1px罫線で境界」設計より濃く、浮きすぎる
|
|
96
|
+
- **P021 `bg-gradient-to-`** → DS にグラデーション定義なし。AI が「それっぽさ」で入れる定番で、テーマ色と無関係な紫青グラデが混入する
|
|
97
|
+
- **P022 `z-[9999]`** → z-50 まで。z-index インフレは overlay 系(Dialog/Toast/Tooltip)の重なり順契約を破壊する
|
|
98
|
+
- **P028 インラインstyleの余白** → Tailwind クラス。style 属性は lint の検出網の外に逃げるため禁止
|
|
99
|
+
- **P031 固定デバイス幅 `w-[375px]`** → `w-full + max-w-*`。特定端末決め打ちは他端末で必ず破綻する
|
|
100
|
+
|
|
101
|
+
## theme / token(P032)
|
|
102
|
+
|
|
103
|
+
- **P032 色を併記しない `border`** → **実害あり(consumer の求人系 Web アプリ)**。Tailwind v4 で border 既定色が currentColor になったため、無色 border は消費側の濃色テキストを透過して黒ずむ。`border-[var(--Border-Low-Emphasis)]` を必ず併記。状態切替系は `border-transparent` + `data-[state=active]:border-[...]` のペアで
|
|
104
|
+
|
|
105
|
+
## accessibility / form(P023–P027)
|
|
106
|
+
|
|
107
|
+
- **P023 `outline-none`** → フォーカスリング削除はキーボード利用者に「今どこにいるか」を消す WCAG 違反。`focus-visible:outline-hidden focus-visible:ring-[3px] ring-[var(--Focus-High-Emphasis)]/50` に置換(`outline-none` は強制配色モードでも枠が出ない。`outline-hidden` は forced-colors 時だけ OS 色の枠が出る。issue #620)
|
|
108
|
+
- **P024 `<div onClick>`** → キーボード・スクリーンリーダーから操作不能。`<Button>`
|
|
109
|
+
- **P025 `<img>` alt なし** → SR が読めない。装飾は `alt=""` を明示
|
|
110
|
+
- **P026 placeholder のみでラベル省略** → SR は placeholder を読まない。入力中に説明が消える。`<Label htmlFor>` + `id`、または `aria-label` / `aria-labelledby` を必須。React Native は `accessibilityLabel` / `accessibilityLabelledBy`(lint は入力タグ内の id / aria-* / accessibility* の有無で判定)
|
|
111
|
+
- **P027 メール欄に `type="text"`** → モバイルのメール用キーボードが出ない・ブラウザ検証が効かない
|
|
112
|
+
|
|
113
|
+
## ai-pattern / animation(P013, P014, P030)
|
|
114
|
+
|
|
115
|
+
- **P013 片側太ボーダー(`border-l-4`)** → AI 生成の定番「カラーバー」。DS の視覚言語(全周1px罫線+Badge でステータス)と異質。全周ボーダー+Badge に置換
|
|
116
|
+
- **P014 pravatar.cc** → 外部依存・不安定。DiceBear shapes を使用
|
|
117
|
+
- **P030 300ms 以上の duration** → 操作フィードバックが「もっさり」する。150/200ms 上限(motion 契約)
|
|
118
|
+
|
|
119
|
+
## component-adoption — ローカル再実装の禁止(P033–P043)
|
|
120
|
+
|
|
121
|
+
すべて同じ失敗を防ぐ: **DS に既にある合成パターンを画面側で手組みすると、
|
|
122
|
+
微妙に違う亜種が増えて後の全画面修正が地獄になる**(v1.41.1 のシート追従バグ修正のような
|
|
123
|
+
一括修正は、消費側が部品を使っている場合にだけ効く)。
|
|
124
|
+
例外を作るときは `ksk-ds-allow-custom-ui` コメントで理由を残す。
|
|
125
|
+
|
|
126
|
+
- **P033 Button 並べた自作 toggle** → `PillToggle`(2–4択)/ `Tabs`(5択+)/ `RadioGroup`
|
|
127
|
+
- **P034 一時的な操作結果を Banner 表示** → `toast.*`。Banner は持続状態用、トーストは瞬間フィードバック用という役割分担
|
|
128
|
+
- **P035 icon button の自作 utility class** → `<Button size="icon*" aria-label>`
|
|
129
|
+
- **P036 EmptyState CTA の className 手組み** → `actionLabel + actionLayout`
|
|
130
|
+
- **P037 SheetHeader + KebabMenu の手配置** → `<DetailSheetHeader trailing={...}>`。grid 契約なしで置くとケバブがズレる(実績あり)
|
|
131
|
+
- **P038 SettingsSection/ListRow の再実装** → DS の `<SettingsSection>` / `<SettingsListRow>`
|
|
132
|
+
- **P039 hidden file input + trigger の再実装** → `<CompactFilePicker>` / `<ImageAttachmentPicker>`
|
|
133
|
+
- **P040 ActionTile/QuickActionGrid の再実装** → DS 版を使用
|
|
134
|
+
- **P041 mobile bottom nav / FAB geometry の手書き CSS** → `<MobileAppShell>` + `<BottomTabBar>` + `<MobileFloatingActionButton>`。safe-area 対応が画面ごとに割れるのを防ぐ
|
|
135
|
+
- **P042 Bottom sheet の外枠 class recipe 手組み** → `<BottomSheetFrame preset>`
|
|
136
|
+
- **P043 Expo Router tabBar の再実装** → `createExpoRouterTabBar(...)` / `<LiquidBottomTabBar>`
|
|
137
|
+
|
|
138
|
+
## AIアンチパターン(AI1–AI10)
|
|
139
|
+
|
|
140
|
+
AI1–AI9 は上記 P013/P021/P019/P017/P020/P009/P015/P007 の再掲(AI が特に犯しやすい順の索引)。
|
|
141
|
+
**AI9(常時ループアニメ)**: `animate-spin/bounce/pulse` はローディング状態限定。静的 UI に常時動く要素を置かない。
|
|
142
|
+
**AI10(文脈非依存違反)**が固有で最重要:
|
|
143
|
+
|
|
144
|
+
> テキスト・背景・border の色を明示せず親の継承や currentColor に委ねると、
|
|
145
|
+
> 消費側が濃色テキスト・色付き背景を敷いた瞬間に枠線・アイコン・文字が化ける(consumer の求人系 Web アプリで実際に発生)。
|
|
146
|
+
> コンポーネントは見た目を自前で固定する: テキスト要素に `text-[var(--Text-*)]`、
|
|
147
|
+
> サーフェスに `bg-[var(--Surface-*)]`+`border-[var(--Border-*)]`。
|
|
148
|
+
> 検出: Storybook ツールバーの **Hostile ctx** を loud にして、マゼンタ化・背景透けが無いか目視。
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# トークン早見リファレンス
|
|
2
|
+
|
|
3
|
+
> 正本は `tokens.json`(機械可読)と `src/styles/*.css` / `src/preset.css`(実 CSS)。
|
|
4
|
+
> 本ファイルは実装時に most-used を引くための早見。迷ったら正本を読む。
|
|
5
|
+
|
|
6
|
+
## カラー — 3層構造の使い分け
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Layer 1 Primitive --Primitive-{Color}-{50..900} ← コンポーネントから直接使うの禁止
|
|
10
|
+
Layer 2 Semantic --{Category}-{Role} ← コンポーネントはここだけを使う
|
|
11
|
+
Layer 3 Bridge --primary 等 shadcn 互換 ← shadcn 移植コードの互換用
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
テーマ差し替えは `--Primitive-Brand-{shade}` スロットを themes/*.css が上書きする仕組み。
|
|
15
|
+
だから **Brand 系は必ず Semantic 経由**(`--Brand-Primary` = Brand-600、`--Brand-Action` = 700)。
|
|
16
|
+
|
|
17
|
+
### Semantic 主要トークン(light。dark は `.dark` で自動反転)
|
|
18
|
+
|
|
19
|
+
| カテゴリ | トークン | 用途 |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Surface | `--Surface-Primary` / `-Secondary` / `-Tertiary` / `-Quaternary` | 白 / 薄灰 / 灰 / 濃灰の面 |
|
|
22
|
+
| | `--Surface-Disable` / `--Surface-Inverse` | 無効面 / 反転面(黒っぽい) |
|
|
23
|
+
| | `--Surface-Accent-Primary` / `-Light` / `-Subtle` | ブランド面 / 薄いブランド面 / 透過ティント |
|
|
24
|
+
| | `--Surface-{Caution,Success,Warning,Info}` | 状態の淡背景(50系) |
|
|
25
|
+
| | `--Surface-{...}-Subtle` | 状態の透過ティント(15%) |
|
|
26
|
+
| | `--Surface-Caution-Strong` | バッジ/ピルの強 fill(500系。Base より一段明るいのは役割違い) |
|
|
27
|
+
| Text | `--Text-High/Medium/Low-Emphasis` <!-- docs-drift-ignore: --Text-High/Medium/Low-Emphasis --> / `--Text-Disable` | 文字の強弱 |
|
|
28
|
+
| | `--Text-on-Inverse` / `--Text-on-Media` | 反転面 / 画像上の白文字 |
|
|
29
|
+
| | `--Text-Accent-Primary` / `--Text-{Success,Caution,Warning,Info}` | 色付き文字(コントラスト確保済み 600–700系) |
|
|
30
|
+
| | `--Text-Caution-on-Inverse` | Surface-Inverse(暗色ツールバー等)上の destructive 文字(Red-400。Text-Caution は暗背景で 2.7:1 しか出ない) |
|
|
31
|
+
| Object | `--Object-High/Medium/Low-Emphasis` <!-- docs-drift-ignore: --Object-High/Medium/Low-Emphasis --> / `--Object-Disable` | アイコン・図形 |
|
|
32
|
+
| | `--Object-{Caution,Success,Warning,Info}` / `--Object-Rating` | 状態アイコン / ★ |
|
|
33
|
+
| Border | `--Border-Low-Emphasis`(区切り・淡カード) / `--Border-Medium-Emphasis`(入力・強調) / `--Border-High-Emphasis` | 罫線3段 |
|
|
34
|
+
| | `--Border-{Caution,Success,Warning,Info}` / `--Border-Accent-Primary` | 状態枠線 |
|
|
35
|
+
| Brand | `--Brand-Primary`(600) / `--Brand-Action`(hover/active、700) / `--Brand-Light` / `--Brand-Ultra-Light` | ブランド |
|
|
36
|
+
| Hover/Active | `--Hover-Primary-Button` 等(600→700→800 の段階) | ボタン状態はこのトークンで(自前で暗くしない) |
|
|
37
|
+
| Focus | `--Focus-High-Emphasis`(Brand-400) | フォーカスリング専用 |
|
|
38
|
+
| Overlay | `--Overlay-Dark/Medium/Light` | モーダル背景等 |
|
|
39
|
+
| 状態基準 | `--Caution-Base` / `--Info-Base`(600系)、`--Success-Base` / `--Warning-Base`(700系。白文字 AA 4.5:1 確保のため) | テキスト/アイコン基準の状態色 |
|
|
40
|
+
|
|
41
|
+
### 使い分けの決まり文句
|
|
42
|
+
|
|
43
|
+
- 白背景 → `bg-[var(--Surface-Primary)]`、薄灰の区画 → `bg-[var(--Surface-Secondary)]`
|
|
44
|
+
- 本文 → `text-[var(--Text-High-Emphasis)]`、補足 → `-Medium`、プレースホルダ的 → `-Low`
|
|
45
|
+
- 区切り線・カード枠 → `border-[var(--Border-Low-Emphasis)]`、入力枠 → `-Medium-Emphasis`
|
|
46
|
+
- エラー文字 → `text-[var(--Text-Caution)]`(Red-700。淡背景 Surface-Caution 上でも AA。fill 用の `--Caution-Base`=Red-600 とは別値)
|
|
47
|
+
|
|
48
|
+
### Categorical(質的パレット・テーマ非依存)
|
|
49
|
+
|
|
50
|
+
`--Categorical-{1..16}`(base: ドット/アイコン)/ `-Subtle`(背景ティント)/ `-Bold`(文字)。
|
|
51
|
+
「N番目のカテゴリ」を区別する用途専用(カレンダー・chip・グラフ系列)。N色必要なら 1..N を順に使う
|
|
52
|
+
(CVD 分離度の高い順に並んでいる)。**文字には必ず `-Bold`**。詳細は `src/styles/categorical.css`。
|
|
53
|
+
|
|
54
|
+
## Typography — typo-* ユーティリティ
|
|
55
|
+
|
|
56
|
+
`typo-{display-xl|display-lg|heading-3xl..sm|body-lg..xs|label-lg..xs|caption}`。
|
|
57
|
+
size/weight/line-height/letter-spacing を1クラスに内包。**色は別指定**:
|
|
58
|
+
`className="typo-body-sm text-[var(--Text-Low-Emphasis)]"`。
|
|
59
|
+
制約: body-xs(10px) と caption(11px) は本文禁止(本文下限 12px)。一覧は `contracts/rules.json` の `typography.classes`。
|
|
60
|
+
|
|
61
|
+
## Spacing — 4px グリッド
|
|
62
|
+
|
|
63
|
+
スケール: 0,4,8,...,60(tokens.json `spacing.scale`)。Tailwind 標準クラス(gap-1=4px, gap-2=8px,
|
|
64
|
+
gap-3=12px, gap-4=16px, gap-6=24px, p-8=32px...)で表現し、**任意値 `p-[17px]` は禁止**。
|
|
65
|
+
高頻度帯は gap/p の 1–6。8 以上(32px+)はセクション区切り等の大きな余白のみ。
|
|
66
|
+
画面端マージン基準 16px(実レイアウトは Screen/Shell の padding contract 優先)。
|
|
67
|
+
|
|
68
|
+
## Radius / Shadow / Motion / TouchTarget
|
|
69
|
+
|
|
70
|
+
- 角丸: 意味トークン `--Radius-Surface`(14) / `--Radius-Modal`(24) / `--Radius-Sheet`(32) を優先。
|
|
71
|
+
素の rounded-* は none/sm(4)/md(6)/lg(8)/xl(12)/2xl(16)/full の7値のみ(P019)
|
|
72
|
+
- 影: `--shadow-sm/md/lg/dialog/tooltip` の5段のみ(P020)。影色は neutral でテーマ非依存
|
|
73
|
+
- motion: 150ms(micro)/ 200ms(enter)/ sheet 280ms spring。300ms+ 禁止(P030)
|
|
74
|
+
- タッチターゲット: min 44px・推奨 48px。chip(32px) は hitSlop で実効 44px(`touchTargets`)
|
|
75
|
+
|
|
76
|
+
## テーマ
|
|
77
|
+
|
|
78
|
+
default(Blue)/blue/cobalt/orange/green/violet。新規は `src/themes/*.css` に Brand 10行差し替えで追加。
|
|
79
|
+
light/dark は Brand 差し替えと**直交2軸**(`.dark` クラス付与で semantic が自動反転、コンポーネント変更不要)。
|