workspace-ui-kit/.claude/skills/designing-workspace-ui/SKILL.md
snc777 f6a781c47e initial commit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 14:24:17 +09:00

224 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: designing-workspace-ui
description: 配布物/workspace-ui-kit のワークスペース UI 作業ペイン修正・コンポーネント追加・色や角丸や余白の変更・レイアウト調整・情報設計の検討・JSX の編集で、shadcn idiom に準拠したコード生成とデザイン規律を強制するスキル。「Pane を変えたい」「ボタンを追加したい」「色を変えたい」「コンポーネントを作りたい」「workspace の見た目を直したい」「余白を直したい」「フォームを追加したい」「レイアウトを調整したい」と依頼された際に使用する。次の場合は使用しない: components/ 配下を編集しない単純な質問・タイポ修正・README やドキュメントのみの編集・openspec/ の ADR 起草のみ・テストコードのみの修正・依存パッケージ更新。
---
# Designing Workspace UI
`配布物/workspace-ui-kit` で UI を編集する際は、以下の2軸を必ず両方適用する:
1. **shadcn idiom に従ってコード生成する** — base UI / semantic token / 親管理の余白
2. **SSoT を経由しないデザイン変更を拒否する** — トークン・部品・パターン・情報設計の不足は4分岐で診断し、ユーザーに確認する
CLAUDE.md の「コード生成ルール」を常時適用の禁止事項として参照する。本スキルはその詳細根拠とプロジェクト固有規律を提供する。
## 依存
このスキルが参照する SSoT:
- `app/globals.css` — デザイントークン(`@theme` 内の CSS 変数)
- `components.json` — shadcn 設定base / style / iconLibrary / alias。ファイルを読んで確認する
- `components/ui/` — shadcn 素体(編集可能。方針は後述)
- `components/primitives/` — プロジェクト固有プリミティブ(`ls` して確認する。名前はハードコードしない)
- `openspec/decision/` — ADRペイン責務・配色・角丸等。番号はハードコードせず `ls` で最新を確認する)
前提: shadcn スキル(`.claude/skills/shadcn/`)がインストール済みであること。ただしこのスキルから shadcn スキルを読みに行く指示は出さない。必要なルールは自己完結で持つ。
## コード生成ルール
CLAUDE.md の禁止事項の根拠と、このプロジェクトでの適用方法を示す。
### 中心の禁止事項
| 禁止 | 正しい方法 | なぜ |
| ---------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------ |
| `space-y-*` / `space-x-*` | `flex flex-col gap-*` / `flex gap-*` | 子要素が条件で消えたとき余白が崩れる。親が管理すれば子が何個でも安定 |
| `className` で色・フォントサイズ・フォントウェイトを上書き | variant / semantic token / CSS 変数 | コピペが蔓延し、ダークモードで対応漏れが起きる。部品側にサイズ展開を用意する |
| 生の色クラス(`bg-blue-500` 等) | `bg-primary` 等の semantic token | テーマ変更時に全ファイル書き換えになる。名前で指定すれば定義 1箇所で済む |
| `w-N h-N`(正方形時) | `size-N` | 「正方形にしたい」意図が明確になる |
| `asChild`radix の API | `render`base の API | このプロジェクトは base を使用(`components.json` で確認。radix の書き方は動かない |
| shadcn 部品がある場面で自前の div | `Badge` / `Separator` / `Skeleton` 等 | a11y・ダークモード・テーマ連動が組み込み済み。自作すると全部欠落する |
このプロジェクトで最も誤りやすいパターン(**必ず暗記**:
```tsx
// Incorrect — radix の書き方は base では動かない
<DialogTrigger asChild>
<Button variant="outline">設定を開く</Button>
</DialogTrigger>
// Correct — base の API
<DialogTrigger render={<Button variant="outline" />}>
設定を開く
</DialogTrigger>
```
その他のパターン(スペーシング・タイポグラフィ・セマンティックカラー・アイコン・コンポジション・フォーム)は [references/coding-rules.md](references/coding-rules.md) を参照。
### components/ui/ の編集方針
shadcn の Open Code 思想に基づき、`components/ui/` は**プロジェクトのコード**として編集してよい。ただし方法に規律がある。
**OK**:
- 部品に新しい variant を追加する(例: `CardTitle``data-size="sm"` を追加)
- 部品の間隔やスタイルを構造的に変更する
- 新しい CSS 変数を `globals.css` に定義して部品から参照する
**NG**:
- 呼び出し側で `className` を使って見た目を毎回打ち消す
- 部品ファイルを丸ごとコピーして別名で作る
部品を編集した後、公式の更新を取り込みたいときは `npx shadcn@latest add <component> --diff <file>` で差分を確認してマージする。
### 出力後セルフレビュー
コードを出力した後、以下の 3点をセルフレビューし、違反があれば修正版を出す:
1. **shadcn の書き方**: 間隔は親管理(`gap-*`)か? 色は名前指定semantic token 部品の見た目を `className` で上書きしていないか?
2. **base 準拠**: `asChild` ではなく `render` を使っているか?
3. **プロジェクトトークン**: `globals.css` の既存トークンで表現できるか?
## SSoT エスカレーション規律
このプロジェクトは教材。受講生が「自分の思想を画面にする」ことがゴール。AI が独断でデザインを決めると受講生の学習機会を奪う。
**SSoT を経由しない UI 変更は禁止。** 既存 SSoT で作れないものが出てきたら、以下の 4分岐で診断し、必ずユーザーに聞く。
### 作業前の確認(必ず実行)
以下のチェックリストを応答にそのままコピーし、各項目を完了したら `[x]` に置き換えながら進む。スキップは禁止。
```
SSoT 把握:
- [ ] app/globals.css を読み、既存の semantic token を列挙した
- [ ] components/ui/ を ls し、利用可能な shadcn 部品を列挙した
- [ ] components/primitives/ を ls し、Inline* 等のプロジェクト固有部品を列挙した
- [ ] openspec/decision/ を ls し、関連する ADR を読了した
```
このチェックが全て埋まる前にコード生成を開始してはならない。
### 4 分岐の決定木
既存 SSoT で作れる → そのまま実装。作れない → 以下に進む。
**いずれの分岐でも、ユーザーの判断なしに実装に進んではならない。**
#### 3a. トークンの穴
色・余白・角丸・影・フォント等の値が既存トークンで足りない。
やること: 何が足りないかを 1行で説明 → `@theme` への追加案を提示 → ユーザーの判断を仰ぐ
やってはいけないこと: 生の色クラスの使用 / 「一時的に hardcoded で後で直す」式の仮対応 / ユーザーに聞かず `@theme` を変更
#### 3b. 部品の穴
既存部品で表現できない形・variant が必要。
やること: 既存部品の variant / size で代替できないか先に試す → 不可能なら新 variant または新プリミティブを起案 → ユーザーの判断を仰ぐ
やってはいけないこと: 部品ファイルを fork コピー / 呼び出し側で className の上書きで済ませる
#### 3c. パターンの穴
レイアウトパターン・複数部品の組み合わせ規則・状態empty / error / loadingの規律がない。
やること: 既存 ADR を読み、本当に規律がないことを確認 → 規律案を起案 → ユーザーの判断を仰ぐ
やってはいけないこと: 「とりあえず置いてみる」で恒久パターンを既成事実化
#### 3d. 情報設計の穴
ペインに何を載せるか・並び順・情報の増減の規律がない。
やること: **コードを書かない**。何を載せるか・優先順位・並び順を質問する → ユーザーが決めてから実装
やってはいけないこと: 「採用管理ならこれが普通だろう」と独断で情報を足す / 削る / 並び替える
### エスカレーションのテンプレート
```
[診断]
何が足りない: <1 行説明>
分岐: 3a / 3b / 3c / 3d のどれか
[根拠]
Refactoring UI の <軸> / ADR の <規律> / shadcn idiom 上の <理由>
[提案]
案1: <内容>(メリット / デメリット)
案2: <内容>(メリット / デメリット)
[ユーザーへの質問]
どちらで進めますか?別案ありますか?
```
### 評価軸Refactoring UI
エスカレーション時の根拠に使う:
- Hierarchy階層/ Spacing余白/ Typographyタイポ/ Color/ Depth/ Polish空状態・エラー状態・ローディング状態・微調整
## ペイン編集導線
### Pane 3 と Pane 4 の責務分離
**「Pane 3 = 読む場所、Pane 4 = 編集の本拠地」**。詳細は `openspec/decision/` 配下の最新 ADR を確認する。
- Pane 3 のカードに inline 編集 UIinput・textarea・編集ボタンを新たに置かない
- 編集機能を足したい時は Pane 4 側に置く
- 「Pane 3 にも編集を持たせたい」と要望が来たら、まず原則との衝突を伝え、本当に必要かを問い直す
### インライン編集プリミティブの再利用
`components/primitives/` の既存プリミティブを再利用する(`ls` して名前を確認すること)。新しい編集 UI のスタイル流派を独自に増やさない。
導入禁止の編集 UI: 鉛筆アイコン式 / 「編集」ボタン式 / フォーム・モーダル一括編集式
### 入力保存規約
- 1 行 `input`: Enter で保存 / Esc でキャンセル / blur で保存
- 複数行 `textarea`: **Cmd+Enter で保存**Enter は改行)/ Esc でキャンセル / blur で保存
- ホバー時のみ薄い枠を出す。常時の枠は出さない
### 担当の用語分離
候補者単位とステージ単位で用語を使い分ける。混ぜない。
- 候補者単位: 「採用担当」
- ステージ単位: 「面接官」(書類選考は「審査担当」)
## 角丸border-radiusの階層ルール
`rounded-*` クラスの選択に迷ったとき、以下の 4 ルールで判断する。役割 × R クラスの対応表は `openspec/changes/add-4pane-workspace-template/mockup-guide.md` の角丸セクションを参照。
### ルール 1: 親 R ≧ 子 R
親の箱に当てた R より大きな R を、その中の要素に付けない。
### ルール 2: 同格の島は同じ R
`bg-card` で囲った「島」は原則 `rounded-lg` に揃える。`Card` 本体だけは `rounded-xl` の例外。
### ルール 3: 厳密な同心までは求めない
Tailwind のスケール(`xl/lg/md/sm`)で段差が視覚的に分かれば十分。
### ルール 4: 高密度 UI での例外
行密度を上げるために `bg-card` の島を `rounded-md` に下げてよい。ただし子要素には `rounded-md` より大きな R を付けない(ルール 1 を維持)。
## React 19 ルール
### Effect 内同期 setState 禁止
`useEffect` の中で同期的に `setState` を呼んで初期値を入れ直すパターンは禁止。
代替パターン:
- 親側で `key` を変更して子コンポーネントを再マウントし、`useState(initialValue)` で初期化する
- フォーカス + 全選択は `autoFocus` + `onFocus={(e) => e.target.select()}` で実現する