diff --git a/.gitignore b/.gitignore index a9b3a1d..d419636 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,12 @@ logs/ .worktrees/ .claude/ .playwright-mcp/ +# Playwright E2E artifacts +test-results/ +playwright-report/ +blob-report/ +ui/test-results/ +ui/playwright-report/ # Agent skill installs (modern-web-guidance etc. via `skills add`) — local tooling, # not project source. .agents/ diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..3364ff3 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,177 @@ +# DESIGN.md — MAESTRO + +> AI エージェントが一貫した日本語 UI を生成するためのデザイン仕様書。 +> `AGENTS.md`(作り方)の隣に置く「見た目と雰囲気」の source of truth。 +> セクションヘッダーは英語、値の説明は日本語([awesome-design-md-jp](https://github.com/kzhrknt/awesome-design-md-jp) の Stitch 拡張フォーマットに準拠)。 +> +> **この文書が視覚判断の正準**。`docs/design/README.md` は改名前・ライトモード前提の旧版で、ここで上書きする。 +> 値はすべて**ライブのコード**(`ui/tailwind.config.js` / `ui/src/index.css`)から採取。色は CSS 変数でライト/ダークを切り替える。 + +--- + +## 1. Visual Theme & Atmosphere + +- **デザイン方針**: Refero 系の「ミニマル+高密度」。装飾を削り、ハイライン(極細罫)で構造を作る。影に頼らない +- **密度**: 情報密度の高い業務 UI。本文 13px の詰まったレイアウト +- **キーワード**: 静か、無彩色、機能的、罫線主導、操作対象に語りかける(人称を出さない) +- **特徴**: ニアブラック(#18181b)を唯一のブランド差し色にしたほぼ無彩色。ライト/ダーク両対応で、ダークは pitch-black を避けやや持ち上げた zinc 調 +- **トーン**: オペレーター向け。感嘆符なし、UI クロムに絵文字を置かない(絵文字はエージェント生成コンテンツ内の限定箇所のみ) + +--- + +## 2. Color Palette & Roles + +色は CSS 変数経由。`*-slate-*` クラス(1454 箇所)がそのままライト/ダークで反転する。**ブランド色はランタイム branding(`/api/branding`)で差し替え可能** — ハードコードしない。 + +### Brand(既定。branding 未設定時のフォールバック) + +| Role | Var | 既定値 | +|---|---|---| +| Primary | `--brand-primary` | `#18181b`(ニアブラック) | +| Primary deep(hover) | `--brand-primary-deep` | `#09090b` | +| Primary soft(選択/active tint・light) | `--brand-primary-soft` | `#f4f4f5` | +| Primary soft(dark) | `--brand-primary-soft` | `#2c2c34` | +| Primary ring(focus) | `--brand-primary-ring` | `rgba(24,24,27,0.25)` | +| Primary fg(差し色上の文字) | `--brand-primary-fg` | `#ffffff` | + +> 旧版の `#2563eb`(blue-600)はモダン化で**廃止**。新規 UI で青を主役にしない。 + +**ブランド色の解決順**: `スペース個別の色(spaces.brand_color)` → `組織/全体 branding(config.yaml / data/branding)` → `既定 #18181b`。スペース(案件)が自分の色を持てる(クライアント別など)。`--brand-primary-fg`(コントラスト文字色)/ `-deep`(hover)/ `-soft`(tint)/ `-ring`(focus)は選択色から導出する。**ハードコードせず必ず `--brand-primary*` 変数を使う**。Space rail のアバター・アクティブ tint も同じ変数で色付く。 + +### Semantic surfaces + +| Role | Var | Light | Dark | +|---|---|---|---| +| Canvas(最背面) | `--canvas` | `#ffffff` | `#18181c` | +| Surface(パネル) | `--surface` | `#fafafa` | `#202024` | +| Surface-2(入れ子) | `--surface-2` | `#f4f4f5` | `#2a2a30` | +| Hairline(罫線) | `--hairline` | `#e4e4e7` | `#3a3a42` | +| Hairline-soft | `--hairline-soft` | `#f4f4f5` | `#2a2a30` | +| Ink(本文) | `--ink` | `#0f172a` | `#e7e7ea` | +| Muted(補助) | `--muted` | `#64748b` | `#a1a1aa` | + +### Neutral ramp(`--slate-50…950`) + +Light = Tailwind 既定 slate(`#f8fafc`→`#020617`)。Dark = 反転 zinc 調(`--slate-50 #18181c` → `--slate-950 #fafafa`)。`50/100` = サーフェス、`700/900` = テキスト、という意味付けで使う。 + +### Status(状態色は Tailwind 既定スケール維持) + +`statusTone()`(`ui/src/lib/utils.ts`)が一元定義。running/success=emerald、waiting/retry=amber、subtasks=indigo、failed=red、queued/cancelled=slate。pastel bg + deep fg のピル。 + +--- + +## 3. Typography Rules + +### 3.1 和文フォント +`IBM Plex Sans JP`(主)→ `Hiragino Sans`(フォールバック)。Google Fonts から読込済み。 + +### 3.2 欧文・等幅フォント +等幅は `JetBrains Mono`(主)→ `IBM Plex Mono`。識別子・ログ・バージョン・cron 式・SMALL-CAPS マイクロラベルに使う。 + +### 3.3 font-family 指定(フォールバック込み) +```css +--font-sans: 'IBM Plex Sans JP', 'Hiragino Sans', system-ui, sans-serif; +--font-mono: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace; +``` + +### 3.4 文字サイズ・ウェイト階層 +- 本文 **13px**(`0.8125rem`)— 高密度の基準。タイトル 18px(詳細)/ 20px(ダイアログ)、チャット 14px、マイクロラベル 11px(`2xs`)/ 10px +- ウェイトは重め。700(bold) が主役(ボタン・ピル・チップ・微小ラベル)、800(extrabold) はタイトルと主 CTA、本文のみ 400/500 +- モバイル入力は `font-size: 16px !important`(iOS 自動ズーム防止) + +### 3.5 行間・字間 +- 本文 `line-height: 1.55`、見出し/詰めたい所 `1.3`、汎用 `1.5` +- **CJK 長文は 1.6–1.8 を推奨**(和文は欧文より行間を広く) +- マイクロ大文字ラベルは `letter-spacing: 0.04em`。和文本文に欧文的なベタ詰めをしない + +### 3.6 禁則処理・改行ルール +- 禁則はブラウザ既定(CJK 句読点・閉じ括弧の行頭禁則)を尊重 +- 長い識別子・URL は `overflow-wrap: anywhere` で折る。和文本文は `word-break: normal`(無理な分割をしない) +- 数字+単位は分離させない: `N 件` / `N分前`(相対時刻は和文 `たった今 / N分前 / N時間前 / N日前`) + +### 3.7 OpenType 機能 +- 和文プロポーショナル詰めが要る見出しに `font-feature-settings: "palt" 1`、カーニング `"kern" 1` +- 等幅(JetBrains Mono)は `font-feature-settings: 'cv11','ss01','ss03'`(コード可読性向けの既存設定) + +### 3.8 縦書き +非対応(業務 UI のため横書き固定)。 + +--- + +## 4. Component Stylings + +実体は `ui/src/components/**`。新規コンポーネントは下記レシピを踏襲する。 + +- **Card / Panel**: `bg-canvas`(入れ子は `bg-surface`)、`border border-hairline`、`rounded-md`(6px)、`shadow-sm`。padding `p-3`〜`p-4` +- **Primary button**: ブランド差し色塗り(`bg-accent text-accent-fg`)、hover で deep。padding `8px 16px`、`rounded-md`、700 +- **Ghost / secondary**: 透明 → hover `bg-surface-2`。罫線つきは `border-hairline` +- **Input**: `bg-canvas border-hairline rounded-md`。focus は `ring-2` + `--brand-primary-ring` +- **Tabs(TopBar)**: 下線タブ。active は下線+ ink、非 active は muted(`components/layout/TopBar.tsx`) +- **Pill / Chip / StatusBadge**: `rounded-full`、pastel bg + deep fg、700。`statusTone()` 準拠 +- **List item**: 入れ子ミニカード。active = `--brand-primary-soft` tint + 罫線昇格 +- **Chat bubble**: user = 差し色塗り `rounded-2xl rounded-br-md`、agent result = emerald 系、ASK = amber 系(`ChatMessage`) +- **Dialog**: 中央、`max-width: min(860px, 92vw)`、`max-height: 88dvh`、内部スクロール、`shadow-md`、overlay は straight alpha(blur 無し) + +### 4.1 Space & Workspace surfaces(本スペックの新面) + +- **Space rail / list**: 左に縦並び。**個人スペースを先頭固定**、案件スペースが続く。各行は list-item レシピ。active = soft tint。可視性(private/org/public)を小さなマイクロラベルで示す +- **Space detail**: 4レーン(資料 / 議事録 / 予定 / チャット)の俯瞰。タブピル or セクションで切替。土台で実体があるのは「チャット」「ファイル」。未実装レーンは**ダミーを出さず**、機能完成時に追加(個人の永続ワークスペースは土台から表示) +- **File 窓**: ツリー(`FileBrowser.tsx`)+ プレビュー/編集(`FilePreview.tsx`)。`border-hairline` で 2 ペイン分割、ヘッダは `sticky bg-surface`。HTML アプリ実行は `