224 lines
12 KiB
Markdown
224 lines
12 KiB
Markdown
---
|
||
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 編集 UI(input・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()}` で実現する
|