@squadbase/vantage 0.6.0-dev.3cc6138 → 0.6.1-dev.90c1a41
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/dist/add-DY4AXANK.js +6 -0
- package/dist/add-DY4AXANK.js.map +1 -0
- package/dist/{build-XXKKX6KB.js → build-JB4VOMUI.js} +9 -9
- package/dist/{build-XXKKX6KB.js.map → build-JB4VOMUI.js.map} +1 -1
- package/dist/{check-X2TDOILH.js → check-ZJYK6RLG.js} +7 -7
- package/dist/{check-X2TDOILH.js.map → check-ZJYK6RLG.js.map} +1 -1
- package/dist/{chunk-SVNOWE5U.js → chunk-6S4BAIGV.js} +2 -2
- package/dist/{chunk-SVNOWE5U.js.map → chunk-6S4BAIGV.js.map} +1 -1
- package/dist/{chunk-VVOXG6ZU.js → chunk-BCE22JSM.js} +186 -12
- package/dist/chunk-BCE22JSM.js.map +1 -0
- package/dist/{chunk-TDUIW7LD.js → chunk-C2CX6GLX.js} +3 -3
- package/dist/chunk-C2CX6GLX.js.map +1 -0
- package/dist/{chunk-LCN36MYX.js → chunk-EP6JHXSR.js} +4 -4
- package/dist/{chunk-LCN36MYX.js.map → chunk-EP6JHXSR.js.map} +1 -1
- package/dist/{chunk-B45WAO5Q.js → chunk-JGRMRXXZ.js} +42 -4
- package/dist/chunk-JGRMRXXZ.js.map +1 -0
- package/dist/{chunk-CIJWVFJD.js → chunk-QI3XQKHS.js} +40 -4
- package/dist/chunk-QI3XQKHS.js.map +1 -0
- package/dist/{chunk-46PPUW6Y.js → chunk-T3FLAGI6.js} +5 -5
- package/dist/{chunk-46PPUW6Y.js.map → chunk-T3FLAGI6.js.map} +1 -1
- package/dist/{chunk-V2FV5OJ6.js → chunk-U2M6HGKQ.js} +4 -4
- package/dist/{chunk-V2FV5OJ6.js.map → chunk-U2M6HGKQ.js.map} +1 -1
- package/dist/{chunk-FVWU275X.js → chunk-ZO62C6T4.js} +3 -3
- package/dist/{chunk-FVWU275X.js.map → chunk-ZO62C6T4.js.map} +1 -1
- package/dist/{chunk-YE4CPCXX.js → chunk-ZVANIULZ.js} +3 -3
- package/dist/{chunk-YE4CPCXX.js.map → chunk-ZVANIULZ.js.map} +1 -1
- package/dist/cli.js +15 -12
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +1 -1
- package/dist/{dev-4MQQDHA4.js → dev-FCEC3UKQ.js} +23 -12
- package/dist/dev-FCEC3UKQ.js.map +1 -0
- package/dist/doc/index.d.ts +39 -0
- package/dist/doc/index.js +38 -0
- package/dist/doc/index.js.map +1 -0
- package/dist/{docs-OTFWTCPW.js → docs-EJJ3BECT.js} +4 -4
- package/dist/{docs-OTFWTCPW.js.map → docs-EJJ3BECT.js.map} +1 -1
- package/dist/{doctor-QXA6DURZ.js → doctor-WHZXPERA.js} +8 -8
- package/dist/doctor-WHZXPERA.js.map +1 -0
- package/dist/{manifest-ttGMFi-Z.d.ts → manifest-DiOjyinq.d.ts} +1 -1
- package/dist/{preview-HVOM27FS.js → preview-OGMCNQUO.js} +13 -5
- package/dist/preview-OGMCNQUO.js.map +1 -0
- package/dist/router/index.d.ts +2 -2
- package/dist/router/index.js +2 -2
- package/dist/{routes-2QRAKMGK.js → routes-GTFO5PUF.js} +6 -6
- package/dist/{routes-2QRAKMGK.js.map → routes-GTFO5PUF.js.map} +1 -1
- package/dist/{search-7A43AZ7M.js → search-6Y422SV6.js} +4 -4
- package/dist/{search-7A43AZ7M.js.map → search-6Y422SV6.js.map} +1 -1
- package/dist/server/node.d.ts +1 -1
- package/dist/slide/index.js +2 -2
- package/dist/table/index.js +1 -1
- package/dist/{types-DQjLpLCs.d.ts → types-CXFlMl8S.d.ts} +1 -1
- package/dist/{upgrade-2QCP7UQQ.js → upgrade-AL4KZZR4.js} +7 -7
- package/dist/{upgrade-2QCP7UQQ.js.map → upgrade-AL4KZZR4.js.map} +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +4 -4
- package/docs/en/agent-skills.md +3 -0
- package/docs/en/changelog.md +30 -0
- package/docs/en/cli-reference.md +35 -1
- package/docs/en/routing.md +31 -4
- package/docs/en/ui-and-theming.md +26 -0
- package/docs/index.json +2 -2
- package/docs/ja/agent-skills.md +3 -0
- package/docs/ja/changelog.md +30 -0
- package/docs/ja/cli-reference.md +34 -1
- package/docs/ja/routing.md +30 -3
- package/docs/ja/ui-and-theming.md +26 -0
- package/package.json +5 -1
- package/skills/vantage-design/SKILL.md +127 -0
- package/skills/vantage-design/references/extract.md +110 -0
- package/skills/vantage-design/references/format.md +172 -0
- package/skills/vantage-design/references/presets.md +82 -0
- package/skills/vantage-design/scripts/contrast.mjs +166 -0
- package/templates/AGENTS.md +17 -0
- package/templates/agents/doc.md +73 -0
- package/templates/agents/page.md +2 -0
- package/templates/agents/slide.md +7 -0
- package/theme.css +141 -0
- package/dist/add-S62E5MSP.js +0 -6
- package/dist/add-S62E5MSP.js.map +0 -1
- package/dist/chunk-B45WAO5Q.js.map +0 -1
- package/dist/chunk-CIJWVFJD.js.map +0 -1
- package/dist/chunk-TDUIW7LD.js.map +0 -1
- package/dist/chunk-VVOXG6ZU.js.map +0 -1
- package/dist/dev-4MQQDHA4.js.map +0 -1
- package/dist/doctor-QXA6DURZ.js.map +0 -1
- package/dist/preview-HVOM27FS.js.map +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# 入力から色・書体・トーンを取り出す
|
|
2
|
+
|
|
3
|
+
どの入力でも、最終的に欲しいのは次の 4 つだけ。取り出したら SKILL.md の手順 2(提案)へ戻る。
|
|
4
|
+
|
|
5
|
+
1. **主色**(ブランドの色。ボタン・リンク・ロゴの色)と、あれば**副色**
|
|
6
|
+
2. **背景の明暗**(白基調か、暗い基調か)
|
|
7
|
+
3. **書体**(見出しと本文の `font-family`。システムフォントで足りるか)
|
|
8
|
+
4. **トーン**(2〜3 語: 「落ち着いた」「明るい」「堅い」…)
|
|
9
|
+
|
|
10
|
+
チャートの 5 色は、主色から直接作るより**主色に最も近いチャートプリセット**を選び、
|
|
11
|
+
`npx @squadbase/vantage-template chart <preset>` で適用する方が安全(5 色の明度差・色覚多様性への
|
|
12
|
+
配慮が済んでいる)。`styles.css` の `vantage-template:chart-preset` マーカーブロックの中は
|
|
13
|
+
**手で編集しない**(次の適用で消える)。主色を `--chart-1` に入れたいときだけ、マーカーブロックの
|
|
14
|
+
**後ろ**に `:root` と `.dark, [data-theme="dark"]` の `--chart-1` 上書きを足し、残り 4 色は
|
|
15
|
+
プリセットに任せる。`--primary` や `--radius` もマーカーの外に書く。
|
|
16
|
+
|
|
17
|
+
## URL(既存サイトに合わせる)
|
|
18
|
+
|
|
19
|
+
ブラウザは要らない。手元にある取得手段(`curl`、Web fetch ツール)で HTML と CSS を読む。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
curl -sL <URL> -o /tmp/site.html
|
|
23
|
+
grep -oiE '<meta[^>]+theme-color[^>]*>' /tmp/site.html # ブラウザの UI 色 = 主色の有力候補
|
|
24
|
+
grep -oiE '<link[^>]+stylesheet[^>]*>' /tmp/site.html # 読むべき CSS
|
|
25
|
+
grep -oiE '<link[^>]+(icon|logo)[^>]*>|<img[^>]+logo[^>]*>' /tmp/site.html # ロゴ
|
|
26
|
+
curl -sL <CSSのURL> -o /tmp/site.css # 相対パスは URL と結合する
|
|
27
|
+
grep -oE -- '--[a-zA-Z0-9-]+:\s*[^;]+' /tmp/site.css | head -80 # CSS カスタムプロパティ
|
|
28
|
+
grep -oE 'font-family:[^;]+' /tmp/site.css | sort | uniq -c | sort -rn | head
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
読む順番:
|
|
32
|
+
|
|
33
|
+
1. **CSS カスタムプロパティ**。`--primary` `--brand` `--color-primary` `--accent` などの名前が
|
|
34
|
+
あれば、それが最も信頼できる。
|
|
35
|
+
2. **`<meta name="theme-color">`**。
|
|
36
|
+
3. **ボタン・リンクの色**: `a {` `.btn` `button` `[class*=primary]` のセレクタの `color` /
|
|
37
|
+
`background-color`。出現回数の多い有彩色が主色。
|
|
38
|
+
4. **背景**: `body` / `html` の `background`。暗ければ「暗い基調」。
|
|
39
|
+
5. **書体**: `body` の `font-family`。Google Fonts の `<link>` があればその family 名。
|
|
40
|
+
|
|
41
|
+
注意:
|
|
42
|
+
|
|
43
|
+
- SPA で HTML がほぼ空のときは、`<script>` より先に CSS の `<link>` を探す。それも無ければ
|
|
44
|
+
ユーザーにスクリーンショットかブランドカラーを聞く(推測で埋めない)。
|
|
45
|
+
- 取得できない(認証・ボット対策)ときは、その旨を伝えてスクリーンショットをもらう。
|
|
46
|
+
- ロゴを使うなら `public/brand/` に保存し、`DESIGN.md` の「ブランド素材」行にパスを書く。
|
|
47
|
+
|
|
48
|
+
## 画像・ロゴ
|
|
49
|
+
|
|
50
|
+
- 画像を見て、背景を除いた**面積の大きい有彩色 1〜2 色**を主色 / 副色とする。
|
|
51
|
+
黒・白・灰は背景の明暗の判断にだけ使う。
|
|
52
|
+
- SVG のロゴなら中身の `fill` / `stroke` を読めば正確な値が取れる。
|
|
53
|
+
- 写真やスクリーンショットは色が揺れるので、近い Tailwind パレット(`var(--color-sky-700)` など)に
|
|
54
|
+
丸めて提案する。
|
|
55
|
+
|
|
56
|
+
## pptx / pdf / 既存の資料
|
|
57
|
+
|
|
58
|
+
- **pptx** は zip。`unzip -p <file>.pptx ppt/theme/theme1.xml` で `<a:clrScheme>`(`accent1`〜
|
|
59
|
+
`accent6`・`dk1`/`lt1` の `srgbClr val`)と `<a:fontScheme>`(`majorFont` = 見出し、
|
|
60
|
+
`minorFont` = 本文。日本語は `<a:ea typeface>`)が取れる。`accent1` が主色、`accent1..5` を
|
|
61
|
+
チャートの候補にできる。
|
|
62
|
+
- **pdf** は色の抽出が難しい。ページを画像として見て「画像・ロゴ」と同じ手順にする。書体は
|
|
63
|
+
`pdffonts` があれば一覧が取れる(無ければ見た目で「明朝 / ゴシック」程度に留める)。
|
|
64
|
+
- **docx / xlsx** も zip で、`word/theme/theme1.xml` / `xl/theme/theme1.xml` に同じ形の
|
|
65
|
+
テーマがある。
|
|
66
|
+
|
|
67
|
+
## 言葉だけ(「落ち着いた感じに」)
|
|
68
|
+
|
|
69
|
+
形容詞を `presets.md` の 4 つに寄せ、そのうえで主色だけを調整する。
|
|
70
|
+
|
|
71
|
+
| 言われたこと | 出発点 |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| 落ち着いた・信頼感・堅い・経営向け・青系 | `calm` |
|
|
74
|
+
| 明るい・元気・勢い・暖かい・営業向け | `vivid` |
|
|
75
|
+
| シンプル・モノクロ・印刷する・資料に貼る | `mono` |
|
|
76
|
+
| 特に無し・標準・おまかせ | `default` |
|
|
77
|
+
| 自然・環境・緑 | `default` の構成でチャートを `forest` に |
|
|
78
|
+
| 華やか・ポップ・紫やピンク | `default` の構成でチャートを `berry` に |
|
|
79
|
+
|
|
80
|
+
当てはまらない言葉は、2 案(例: `calm` と `default`)を並べて選んでもらう。
|
|
81
|
+
|
|
82
|
+
## 外部の DESIGN.md(Stitch などが書いたもの)
|
|
83
|
+
|
|
84
|
+
外部の DESIGN.md は YAML frontmatter や本文に**値**(hex・px・フォント名)を持っていることが多い。
|
|
85
|
+
Vantage の `DESIGN.md` は値を持たないので、**値を `styles.css` へ移し、`DESIGN.md` をトークン参照に
|
|
86
|
+
書き直す**。
|
|
87
|
+
|
|
88
|
+
1. 値を拾う: primary / secondary / surface / background / on-* / error / success / warning、
|
|
89
|
+
フォント、角丸。
|
|
90
|
+
2. 対応づける:
|
|
91
|
+
|
|
92
|
+
| 外部の名前 | Vantage のトークン |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| primary / on-primary | `--primary` / `--primary-foreground` |
|
|
95
|
+
| secondary / tertiary | `--chart-2` / `--chart-3` など(チャートで使うなら)。面の色なら `--secondary` |
|
|
96
|
+
| background / surface / surface-container | `--background` / `--card` / `--muted` |
|
|
97
|
+
| on-background / on-surface / on-surface-variant | `--foreground` / `--card-foreground` / `--muted-foreground` |
|
|
98
|
+
| outline | `--border` |
|
|
99
|
+
| error | `--destructive` |
|
|
100
|
+
| success / warning | 専用トークンなし → `--chart-*` のどれかに割り当てて `DESIGN.md` に書く |
|
|
101
|
+
| radius / corner | `--radius` |
|
|
102
|
+
| display / headline font | `--slide-font-display`(+ ページの見出しなら `body` の font-family) |
|
|
103
|
+
| body font | `body` セレクタの font-family と `--slide-font-body`(`:root` の font-family は効かない) |
|
|
104
|
+
|
|
105
|
+
3. `styles.css` のマーカーブロックの外に、`:root` と `.dark, [data-theme="dark"]` の両方で書く
|
|
106
|
+
(チャート色・書体の書き方は SKILL.md の手順 3)。外部の DESIGN.md に
|
|
107
|
+
ダークの値が無ければ、ライトの色相を保って明度だけ反転した値を作り、コントラストを確かめる。
|
|
108
|
+
4. `DESIGN.md` を `format.md` の節の順番で書き直す。外部の文章(トーン・Do/Don't・コンポーネントの
|
|
109
|
+
ルール)は活かし、値だけをトークン名に置き換える。150 行に収まらない分は要約する。
|
|
110
|
+
5. 元のファイルは消さずに残すか(例: `docs/design-source.md`)、ユーザーに確認して削除する。
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# DESIGN.md の書式
|
|
2
|
+
|
|
3
|
+
`DESIGN.md` はプロジェクトルートに置く、**ユーザーが所有する**ファイル。アプリの見た目の意図と
|
|
4
|
+
使い分けのルールを、エージェントが UI を書く前に読める形で残す。`vantage upgrade` も
|
|
5
|
+
`vantage add agents` も書き換えない。
|
|
6
|
+
|
|
7
|
+
## 原則
|
|
8
|
+
|
|
9
|
+
- **値を書かない。トークン名だけを書く。** 色コード(`#…`・`oklch(…)`・`rgb(…)`・`hsl(…)`)や
|
|
10
|
+
px 値の色・書体の実値は `styles.css` の持ち物。`DESIGN.md` には `--primary` のようなトークン名と、
|
|
11
|
+
Tailwind のセマンティッククラス(`text-muted-foreground`)・サイズの段階(`text-2xl`)だけを書く。
|
|
12
|
+
パレット名で色味を説明するのは可(「青 → ティール → …」)。
|
|
13
|
+
- **150 行以内。** 超えると `vantage check` が `DESIGN_MD_TOO_LONG` を警告する。エージェントが
|
|
14
|
+
毎回全文を読むファイルなので、網羅より判断に効くルールを優先する。
|
|
15
|
+
- **YAML frontmatter は付けない。** 先頭は下の「冒頭のコメント」から始める。
|
|
16
|
+
- **会話中の指示が優先。** `DESIGN.md` は既定値であって、個別の依頼を拒む根拠にしない。
|
|
17
|
+
- ロゴ・画像は `public/` 配下のパスで参照する(`public/brand/logo.svg`)。画像を埋め込まない。
|
|
18
|
+
|
|
19
|
+
## 節の順番と見出し
|
|
20
|
+
|
|
21
|
+
見出しは日本語 + 英語の括弧書き(外部の DESIGN.md — Stitch など — の節と対応づけやすくするため)。
|
|
22
|
+
この順番を崩さない。無い情報の節は消さずに「特になし」と書く。
|
|
23
|
+
|
|
24
|
+
| # | 見出し | 書くこと |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| 0 | 冒頭のコメント(`<!-- … -->`) | 何のファイルか / 値は styles.css / 会話の指示が優先 / 「このサイトに合わせて」で更新できること / upgrade が触らないこと |
|
|
27
|
+
| 1 | `## 全体のトーン (Overview)` | 2〜4 行のトーン。最後に「ブランド素材:」行(任意。`public/` のパス) |
|
|
28
|
+
| 2 | `## 色 (Colors)` | 役割 → トークンの表。行は **主色 / 強調 / 良い / 悪い / 注意 / 背景の段階 / 境界 / 文字**。専用トークンが無い役割は「専用トークンなし」+ 代替 |
|
|
29
|
+
| 3 | `## チャート (Charts)` | 系列の順番(`--chart-1..5` とその色味)、1 系列だけ強調するときの色、良い / 悪いの色、禁止の組み合わせ、プリセット名 |
|
|
30
|
+
| 4 | `## 書体 (Typography)` | 見出し / 本文 / 数字 / スライドの書体(`--slide-font-display` / `--slide-font-body`)と、サイズの段階(Tailwind クラス・`--slide-size-*`) |
|
|
31
|
+
| 5 | `## レイアウトと密度 (Layout)` | カード・余白(`gap-*`)・`--radius`・並べ方・密度 |
|
|
32
|
+
| 6 | `## 成果物の種類ごとの規則 (Per-artifact)` | `### ダッシュボード` と `### スライド` の小節(他の種類があれば小節を足す) |
|
|
33
|
+
| 7 | `## Do / Don't` | 3 つずつ程度 |
|
|
34
|
+
|
|
35
|
+
外部の DESIGN.md の対応: Overview / Colors / Typography / Layout(Spacing・Elevation 含む)/
|
|
36
|
+
Components → 「成果物の種類ごとの規則」/ Do's and Don'ts。値は `styles.css` へ移す
|
|
37
|
+
(→ `extract.md` の「外部の DESIGN.md」)。
|
|
38
|
+
|
|
39
|
+
## 使えるトークン
|
|
40
|
+
|
|
41
|
+
| 系統 | トークン |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| 面と文字 | `--background` `--foreground` `--card` `--card-foreground` `--popover` `--popover-foreground` |
|
|
44
|
+
| 主色など | `--primary` `--primary-foreground` `--secondary` `--secondary-foreground` `--accent` `--accent-foreground` `--muted` `--muted-foreground` `--destructive` `--destructive-foreground` |
|
|
45
|
+
| 境界 | `--border` `--input` `--ring` |
|
|
46
|
+
| チャート | `--chart-1` 〜 `--chart-5` |
|
|
47
|
+
| 形 | `--radius` |
|
|
48
|
+
| サイドバー | `--sidebar` `--sidebar-foreground` `--sidebar-primary` … |
|
|
49
|
+
| スライド | `--slide-bg` `--slide-fg` `--slide-accent` `--slide-muted` `--slide-radius` `--slide-font-display` `--slide-font-body` `--slide-size-hero` `--slide-size-body` |
|
|
50
|
+
|
|
51
|
+
- `--muted` `--accent` `--secondary` `--border` は背景・境界用。文字色の役割に割り当てない。
|
|
52
|
+
- 良い / 注意の専用トークンは無い。`--chart-*` の中から割り当てるか、「専用トークンなし」と書く。
|
|
53
|
+
- ページ本文の書体はトークンではなく `body` の `font-family`(`styles.css` の `body` セレクタで上書きする。
|
|
54
|
+
`:root` / `html` に書いても `theme.css` の `body` 指定に負けて効かない)。
|
|
55
|
+
- `--slide-bg` などは既定で `--background` などの別名。`.dark` に書き直す必要は無い。
|
|
56
|
+
|
|
57
|
+
## 雛形(中立の既定テーマ)
|
|
58
|
+
|
|
59
|
+
ベーステンプレート(`packages/vantage-template/template/DESIGN.md`)と**同じ内容**。どちらかを
|
|
60
|
+
直したらもう片方も合わせること。既定テーマ(無彩色の `--primary`、チャートは `blue` プリセット)を
|
|
61
|
+
そのまま説明しているので、新規に作るときはこれを写して、変えた役割の行だけを書き換える。
|
|
62
|
+
|
|
63
|
+
````markdown
|
|
64
|
+
<!--
|
|
65
|
+
DESIGN.md — このアプリの「見た目の意図」を書くファイルです。
|
|
66
|
+
|
|
67
|
+
- 実際の色・角丸・書体の値は src/styles.css にあります。ここにはトークン名(--primary など)と
|
|
68
|
+
使い分けのルールだけを書き、色コードは書きません。
|
|
69
|
+
- エージェントはページ・スライド・コンポーネントを書く前にこのファイルを読みます。
|
|
70
|
+
会話の中での指示はこのファイルより優先されます。
|
|
71
|
+
- 「このサイトに合わせて」「色を落ち着いた感じに」と頼めば、このファイルと styles.css を
|
|
72
|
+
まとめて更新します。
|
|
73
|
+
- このファイルはあなたのものです。`vantage upgrade` が書き換えることはありません。
|
|
74
|
+
-->
|
|
75
|
+
|
|
76
|
+
# デザイン
|
|
77
|
+
|
|
78
|
+
## 全体のトーン (Overview)
|
|
79
|
+
|
|
80
|
+
- 落ち着いた無彩色のベースに、データだけが色を持つ業務ダッシュボード。
|
|
81
|
+
- 装飾より読みやすさを優先する。影・グラデーション・アニメーションは最小限。
|
|
82
|
+
- 数字が主役。1 画面で伝えたいことを 1 つに絞り、補足は小さく添える。
|
|
83
|
+
- ブランド素材: なし(ロゴを使う場合は `public/brand/logo.svg` のように `public/` 配下のパスで書く)
|
|
84
|
+
|
|
85
|
+
## 色 (Colors)
|
|
86
|
+
|
|
87
|
+
色は必ずトークン(Tailwind のセマンティッククラス)で指定する。素のパレット(`bg-blue-600` など)や
|
|
88
|
+
色コードを直接書かない。
|
|
89
|
+
|
|
90
|
+
| 役割 | トークン | 使う場所 |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| 主色 (Primary) | `--primary` / `--primary-foreground` | 主要ボタン、選択中の状態。既定は無彩色 |
|
|
93
|
+
| 強調 (Accent) | `--chart-1` | 1 つだけ目立たせたい数値・系列・リンク的な強調 |
|
|
94
|
+
| 良い (Positive) | `--chart-2` | 前期比のプラスなど、良い変化の小さな印 |
|
|
95
|
+
| 悪い (Negative) | `--destructive` | 前期比のマイナス、エラー、削除操作 |
|
|
96
|
+
| 注意 (Warning) | 専用トークンなし | 文言とアイコンで示し、色は `--muted-foreground` |
|
|
97
|
+
| 背景の段階 | `--background` → `--card` → `--muted` | ページ → カード → カード内の区画・ホバー |
|
|
98
|
+
| 境界 | `--border` / `--input` / `--ring` | 罫線、入力欄、フォーカス |
|
|
99
|
+
| 文字 | `--foreground` / `--muted-foreground` | 本文 / 補足・ラベル・単位 |
|
|
100
|
+
|
|
101
|
+
- `--muted`・`--accent`・`--secondary`・`--border` は背景・境界用。文字色に使わない。
|
|
102
|
+
- 増減(▲▼・前期比)は向きで色を分ける: 増加・プラスは `--chart-2`(または `--primary`)、
|
|
103
|
+
減少・マイナスは `--destructive`。下向きの矢印やマイナスを `--primary` で塗らない。
|
|
104
|
+
- ライトとダークの両方がトークンで決まるので `dark:` を並べない。
|
|
105
|
+
|
|
106
|
+
## チャート (Charts)
|
|
107
|
+
|
|
108
|
+
- 系列の順番は `--chart-1` → `--chart-2` → `--chart-3` → `--chart-4` → `--chart-5`
|
|
109
|
+
(現在はプリセット `blue`: 青 → ティール → フクシア → バイオレット → グレー)。
|
|
110
|
+
- 1 系列だけを目立たせるときは、その系列を `--chart-1`、残りをすべて `--chart-5`(グレー)にする。
|
|
111
|
+
- 良い / 悪いを色で塗り分けるときは `--chart-2` / `--destructive`。色だけに頼らず ▲▼ や符号も添える。
|
|
112
|
+
- 系列は 5 つまで。それ以上はグループ化するか「その他」にまとめる。
|
|
113
|
+
- 禁止: 同じチャートで `--destructive` を普通の系列色として使う(悪い値に見える)。
|
|
114
|
+
- 禁止: 隣り合う系列に `--chart-3` と `--chart-4` を並べて細い線で描く(見分けにくい)。
|
|
115
|
+
- 配色を丸ごと変えるときは `npx @squadbase/vantage-template chart <preset>` を使う
|
|
116
|
+
(`blue` / `ocean` / `sunset` / `forest` / `berry` / `mono`)。
|
|
117
|
+
|
|
118
|
+
## 書体 (Typography)
|
|
119
|
+
|
|
120
|
+
| 用途 | 指定 | 備考 |
|
|
121
|
+
| --- | --- | --- |
|
|
122
|
+
| 見出し・本文 | システムフォント(`body` の `font-family`) | Web フォントは使わない |
|
|
123
|
+
| 数字 | 同上 + `tabular-nums` | 桁がそろうように必ず付ける |
|
|
124
|
+
| スライドの見出し | `--slide-font-display` | 既定は日本語を含むシステムフォント |
|
|
125
|
+
| スライドの本文 | `--slide-font-body` | 既定は見出しと同じ |
|
|
126
|
+
|
|
127
|
+
サイズの段階(ダッシュボード):
|
|
128
|
+
|
|
129
|
+
- ページ見出し: `text-2xl font-bold`
|
|
130
|
+
- カード見出し・ラベル: `text-sm font-medium text-muted-foreground`
|
|
131
|
+
- KPI の数値: `text-3xl font-semibold tabular-nums`
|
|
132
|
+
- 本文・表: `text-sm`
|
|
133
|
+
- 注釈・出典: `text-xs text-muted-foreground`
|
|
134
|
+
|
|
135
|
+
スライドのサイズは `--slide-size-hero`(表紙・大きな数字)と `--slide-size-body`(本文)を基準にする。
|
|
136
|
+
|
|
137
|
+
## レイアウトと密度 (Layout)
|
|
138
|
+
|
|
139
|
+
- 情報はカード(`bg-card` + `border-border`)で区切る。角丸は `--radius` に従う(個別に変えない)。
|
|
140
|
+
- グリッドの間隔は `gap-4`。セクション間は `gap-6` 程度。
|
|
141
|
+
- KPI は 1 行に 2〜4 枚。その下にチャート、最後に明細の表。
|
|
142
|
+
- 密度は「中」。余白を削って詰め込むより、ページを分ける。
|
|
143
|
+
|
|
144
|
+
## 成果物の種類ごとの規則 (Per-artifact)
|
|
145
|
+
|
|
146
|
+
### ダッシュボード
|
|
147
|
+
|
|
148
|
+
- 先頭に KPI カード、次にトレンドのチャート、最後に明細の表。
|
|
149
|
+
- 各 KPI には比較対象(前月比・目標比など)を 1 つ添える。
|
|
150
|
+
- チャートのタイトルは結論を書く(「売上推移」より「売上は 3 か月連続で増加」)。
|
|
151
|
+
|
|
152
|
+
### スライド
|
|
153
|
+
|
|
154
|
+
- 1 枚に 1 メッセージ。見出しに結論を書く。
|
|
155
|
+
- 色は `--slide-bg` / `--slide-fg` / `--slide-accent` / `--slide-muted` を使う
|
|
156
|
+
(既定では `--background` / `--foreground` / `--primary` / `--muted-foreground` に連動)。
|
|
157
|
+
- 強調色は 1 枚につき 1 か所まで。
|
|
158
|
+
|
|
159
|
+
## Do / Don't
|
|
160
|
+
|
|
161
|
+
Do:
|
|
162
|
+
|
|
163
|
+
- トークンと Tailwind のセマンティッククラスで色を指定する。
|
|
164
|
+
- 数値には単位と比較対象を付ける。
|
|
165
|
+
- 色の意味(良い / 悪い / 強調)をアプリ全体でそろえる。
|
|
166
|
+
|
|
167
|
+
Don't:
|
|
168
|
+
|
|
169
|
+
- 色コードや素のパレットクラスを直接書く。
|
|
170
|
+
- 1 画面で強調色を何か所にも使う。
|
|
171
|
+
- 3D チャート・円グラフの多用・装飾目的のグラデーション。
|
|
172
|
+
````
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# 初期デザインのプリセット
|
|
2
|
+
|
|
3
|
+
プロジェクト作成時に選ぶ 4 つの出発点。**id(`default` / `calm` / `vivid` / `mono`)はプロジェクト
|
|
4
|
+
作成のワークフローが参照するので変えないこと。** どれも「チャートのプリセット 1 つ + 必要なら
|
|
5
|
+
`--primary` の上書き + `DESIGN.md` の差分」でできている。
|
|
6
|
+
|
|
7
|
+
適用の手順は共通:
|
|
8
|
+
|
|
9
|
+
1. `npx @squadbase/vantage-template chart <チャートのプリセット>` で `styles.css` のマーカーブロックを
|
|
10
|
+
差し替える。**マーカーブロックの中(`--chart-1..5`)は手で編集しない** ― コマンドの生成物で、
|
|
11
|
+
次の適用で消える。
|
|
12
|
+
2. `--primary` の上書きがあるプリセットは、`styles.css` のマーカーの**外**(先頭の `:root` ブロック)に
|
|
13
|
+
`:root` と `.dark, [data-theme="dark"]` の両方を書く。
|
|
14
|
+
3. `DESIGN.md` を `format.md` の雛形から作り、下の「DESIGN.md の差分」の行だけを書き換える。
|
|
15
|
+
4. `scripts/contrast.mjs` で `--primary-foreground` / `--primary` をライトとダークで確かめる。
|
|
16
|
+
|
|
17
|
+
| id | トーン | チャートのプリセット | `--primary` |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| `default` | 中立・無彩色のベース。データだけが色を持つ | `blue` | 上書きしない(既定の無彩色) |
|
|
20
|
+
| `calm` | 落ち着いた寒色。報告書・経営向け | `ocean` | 任意で深い青 |
|
|
21
|
+
| `vivid` | 明るい暖色。営業・マーケティング向け | `sunset` | 濃いオレンジ |
|
|
22
|
+
| `mono` | モノクロ。印刷・資料への貼り付け向け | `mono` | 上書きしない |
|
|
23
|
+
|
|
24
|
+
## `default`
|
|
25
|
+
|
|
26
|
+
- トーン: 落ち着いた無彩色のベースに、データだけが色を持つ業務ダッシュボード。装飾より読みやすさ。
|
|
27
|
+
- チャート: `blue`(青 → ティール → フクシア → バイオレット → グレー)。
|
|
28
|
+
- `styles.css`: チャートのブロックだけ。`--primary` は触らない。
|
|
29
|
+
- `DESIGN.md`: 雛形そのまま(`format.md` の雛形は `default` を説明している)。
|
|
30
|
+
|
|
31
|
+
## `calm`
|
|
32
|
+
|
|
33
|
+
- トーン: 寒色でまとめた静かな画面。強調は控えめにし、数字と罫線で読ませる。
|
|
34
|
+
- チャート: `ocean`(スカイ → シアン → インディゴ → ティール → スレート)。
|
|
35
|
+
- `--primary`(任意。ボタンにも色を持たせたいときだけ):
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
:root {
|
|
39
|
+
--primary: var(--color-sky-700);
|
|
40
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
41
|
+
}
|
|
42
|
+
.dark,
|
|
43
|
+
[data-theme="dark"] {
|
|
44
|
+
--primary: var(--color-sky-300);
|
|
45
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `DESIGN.md` の差分: 「全体のトーン」を上の文に。チャートの色味を「スカイ → シアン → インディゴ →
|
|
50
|
+
ティール → スレート」に。良い = `--chart-4`(ティール)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
51
|
+
禁止: `--chart-1` と `--chart-2` を隣り合う細い線で並べる(どちらも明るい青系)。
|
|
52
|
+
|
|
53
|
+
## `vivid`
|
|
54
|
+
|
|
55
|
+
- トーン: 明るく勢いのある暖色。KPI とトレンドを大きく見せ、強調色をはっきり使う。
|
|
56
|
+
- チャート: `sunset`(オレンジ → アンバー → ローズ → イエロー → ストーン)。
|
|
57
|
+
- `--primary`(オレンジ 600 は白文字で 4.5:1 に届かないので 700 を使う):
|
|
58
|
+
|
|
59
|
+
```css
|
|
60
|
+
:root {
|
|
61
|
+
--primary: var(--color-orange-700);
|
|
62
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
63
|
+
}
|
|
64
|
+
.dark,
|
|
65
|
+
[data-theme="dark"] {
|
|
66
|
+
--primary: var(--color-orange-400);
|
|
67
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- `DESIGN.md` の差分: トーンを上の文に。主色の行を「濃いオレンジ」に。良い = 専用色なし(▲ と
|
|
72
|
+
`--foreground`)、悪い = `--destructive`。禁止: `--chart-3`(ローズ)と `--destructive` を同じ
|
|
73
|
+
チャートに置く(悪い値と区別できない)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
74
|
+
|
|
75
|
+
## `mono`
|
|
76
|
+
|
|
77
|
+
- トーン: 白黒と灰色だけ。色で意味を運ばず、太さ・順番・ラベルで読ませる。
|
|
78
|
+
- チャート: `mono`(ジンク 900 → 200。ダークでは反転)。
|
|
79
|
+
- `styles.css`: チャートのブロックだけ。`--primary` は触らない(既定が無彩色)。
|
|
80
|
+
- `DESIGN.md` の差分: トーンを上の文に。強調 = `--chart-1`(最も濃い灰)。良い = 専用色なし(▲ と
|
|
81
|
+
符号)、悪い = `--destructive`(**画面で唯一の有彩色**として使う)。チャートは系列を 3 つまでにし、
|
|
82
|
+
それ以上は直接ラベルを付ける。禁止: 隣り合う `--chart-4` と `--chart-5`(明度差が小さい)。
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// WCAG 2.x contrast ratio between two CSS colours. No dependencies.
|
|
3
|
+
//
|
|
4
|
+
// node contrast.mjs <foreground> <background>
|
|
5
|
+
// node contrast.mjs '#ffffff' 'oklch(0.205 0 0)'
|
|
6
|
+
// node contrast.mjs 'oklch(0.985 0 0)' 'var(--color-sky-700)'
|
|
7
|
+
//
|
|
8
|
+
// Accepts: #rgb / #rgba / #rrggbb / #rrggbbaa, rgb()/rgba(), oklch(), and
|
|
9
|
+
// Tailwind palette references `var(--color-<name>-<step>)` (resolved from
|
|
10
|
+
// node_modules/tailwindcss/theme.css, searched upward from the cwd).
|
|
11
|
+
// A translucent foreground is composited over the background first; the
|
|
12
|
+
// background is treated as opaque.
|
|
13
|
+
|
|
14
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
15
|
+
import { dirname, join } from "node:path"
|
|
16
|
+
|
|
17
|
+
function usage(message) {
|
|
18
|
+
if (message) console.error(`error: ${message}`)
|
|
19
|
+
console.error("usage: node contrast.mjs <foreground> <background>")
|
|
20
|
+
console.error(" colours: #hex, rgb(), oklch(), var(--color-<name>-<step>)")
|
|
21
|
+
process.exit(2)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// --- parsing ---------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
function parseNumber(token, percentScale = 1) {
|
|
27
|
+
const t = token.trim()
|
|
28
|
+
if (t === "none") return 0
|
|
29
|
+
if (t.endsWith("%")) return (Number.parseFloat(t) / 100) * percentScale
|
|
30
|
+
const n = Number.parseFloat(t)
|
|
31
|
+
if (Number.isNaN(n)) throw new Error(`not a number: ${token}`)
|
|
32
|
+
return n
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function splitArgs(body) {
|
|
36
|
+
const [main, alpha] = body.split("/")
|
|
37
|
+
const parts = main.trim().split(/[\s,]+/).filter(Boolean)
|
|
38
|
+
return { parts, alpha: alpha === undefined ? 1 : parseNumber(alpha, 1) }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function srgbToLinear(c) {
|
|
42
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function linearToSrgb(c) {
|
|
46
|
+
const v = Math.min(1, Math.max(0, c))
|
|
47
|
+
return v <= 0.0031308 ? v * 12.92 : 1.055 * v ** (1 / 2.4) - 0.055
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Returns gamma-encoded sRGB channels in [0, 1] plus alpha.
|
|
51
|
+
function parseHex(input) {
|
|
52
|
+
let hex = input.slice(1)
|
|
53
|
+
if (![3, 4, 6, 8].includes(hex.length) || /[^0-9a-f]/i.test(hex)) {
|
|
54
|
+
throw new Error(`bad hex colour: ${input}`)
|
|
55
|
+
}
|
|
56
|
+
if (hex.length <= 4) hex = [...hex].map((c) => c + c).join("")
|
|
57
|
+
const n = (i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255
|
|
58
|
+
return { r: n(0), g: n(2), b: n(4), a: hex.length === 8 ? n(6) : 1 }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function parseRgb(body) {
|
|
62
|
+
const { parts, alpha } = splitArgs(body)
|
|
63
|
+
if (parts.length === 4) return parseRgb(`${parts.slice(0, 3).join(" ")} / ${parts[3]}`)
|
|
64
|
+
if (parts.length !== 3) throw new Error(`bad rgb(): ${body}`)
|
|
65
|
+
const [r, g, b] = parts.map((p) => parseNumber(p, 255) / 255)
|
|
66
|
+
return { r, g, b, a: alpha }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function parseOklch(body) {
|
|
70
|
+
const { parts, alpha } = splitArgs(body)
|
|
71
|
+
if (parts.length !== 3) throw new Error(`bad oklch(): ${body}`)
|
|
72
|
+
const L = parseNumber(parts[0], 1)
|
|
73
|
+
const C = parseNumber(parts[1], 0.4)
|
|
74
|
+
const H = (Number.parseFloat(parts[2]) || 0) * (Math.PI / 180)
|
|
75
|
+
const a = C * Math.cos(H)
|
|
76
|
+
const bb = C * Math.sin(H)
|
|
77
|
+
const l_ = (L + 0.3963377774 * a + 0.2158037573 * bb) ** 3
|
|
78
|
+
const m_ = (L - 0.1055613458 * a - 0.0638541728 * bb) ** 3
|
|
79
|
+
const s_ = (L - 0.0894841775 * a - 1.291485548 * bb) ** 3
|
|
80
|
+
const r = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_
|
|
81
|
+
const g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_
|
|
82
|
+
const b = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_
|
|
83
|
+
return { r: linearToSrgb(r), g: linearToSrgb(g), b: linearToSrgb(b), a: alpha }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let tailwindTheme
|
|
87
|
+
function findTailwindTheme() {
|
|
88
|
+
if (tailwindTheme !== undefined) return tailwindTheme
|
|
89
|
+
tailwindTheme = null
|
|
90
|
+
let dir = process.cwd()
|
|
91
|
+
for (;;) {
|
|
92
|
+
for (const rel of [
|
|
93
|
+
"node_modules/tailwindcss/theme.css",
|
|
94
|
+
"node_modules/@squadbase/vantage/node_modules/tailwindcss/theme.css",
|
|
95
|
+
]) {
|
|
96
|
+
const file = join(dir, rel)
|
|
97
|
+
if (existsSync(file)) {
|
|
98
|
+
tailwindTheme = readFileSync(file, "utf8")
|
|
99
|
+
return tailwindTheme
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const parent = dirname(dir)
|
|
103
|
+
if (parent === dir) return tailwindTheme
|
|
104
|
+
dir = parent
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function resolveVar(input) {
|
|
109
|
+
const name = input.match(/^var\(\s*(--color-[a-z]+-\d+)\s*\)$/)?.[1]
|
|
110
|
+
if (!name) throw new Error(`only var(--color-<name>-<step>) can be resolved: ${input}`)
|
|
111
|
+
const theme = findTailwindTheme()
|
|
112
|
+
if (!theme) throw new Error(`tailwindcss/theme.css not found from ${process.cwd()}; pass the value instead`)
|
|
113
|
+
const value = theme.match(new RegExp(`${name}:\\s*([^;]+);`))?.[1]
|
|
114
|
+
if (!value) throw new Error(`${name} is not in tailwindcss/theme.css`)
|
|
115
|
+
return value.trim()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function parseColor(raw) {
|
|
119
|
+
const input = raw.trim().toLowerCase()
|
|
120
|
+
if (input.startsWith("#")) return parseHex(input)
|
|
121
|
+
if (input.startsWith("var(")) return parseColor(resolveVar(input))
|
|
122
|
+
const fn = input.match(/^([a-z]+)\((.*)\)$/)
|
|
123
|
+
if (fn) {
|
|
124
|
+
if (fn[1] === "rgb" || fn[1] === "rgba") return parseRgb(fn[2])
|
|
125
|
+
if (fn[1] === "oklch") return parseOklch(fn[2])
|
|
126
|
+
}
|
|
127
|
+
throw new Error(`unsupported colour: ${raw}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// --- contrast --------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
function composite(fg, bg) {
|
|
133
|
+
const mix = (f, b) => f * fg.a + b * (1 - fg.a)
|
|
134
|
+
return { r: mix(fg.r, bg.r), g: mix(fg.g, bg.g), b: mix(fg.b, bg.b), a: 1 }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function luminance({ r, g, b }) {
|
|
138
|
+
return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function toHex({ r, g, b }) {
|
|
142
|
+
const h = (c) => Math.round(Math.min(1, Math.max(0, c)) * 255).toString(16).padStart(2, "0")
|
|
143
|
+
return `#${h(r)}${h(g)}${h(b)}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const [fgArg, bgArg] = process.argv.slice(2)
|
|
147
|
+
if (!fgArg || !bgArg) usage()
|
|
148
|
+
|
|
149
|
+
let fg
|
|
150
|
+
let bg
|
|
151
|
+
try {
|
|
152
|
+
bg = { ...parseColor(bgArg), a: 1 }
|
|
153
|
+
fg = composite(parseColor(fgArg), bg)
|
|
154
|
+
} catch (error) {
|
|
155
|
+
usage(error.message)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const [hi, lo] = [luminance(fg), luminance(bg)].sort((x, y) => y - x)
|
|
159
|
+
const ratio = (hi + 0.05) / (lo + 0.05)
|
|
160
|
+
const verdict = (min) => (ratio >= min ? "PASS" : "FAIL")
|
|
161
|
+
|
|
162
|
+
console.log(`foreground ${fgArg} (${toHex(fg)})`)
|
|
163
|
+
console.log(`background ${bgArg} (${toHex(bg)})`)
|
|
164
|
+
console.log(`contrast ${ratio.toFixed(2)}:1`)
|
|
165
|
+
console.log(`AA normal text (>= 4.5:1): ${verdict(4.5)}`)
|
|
166
|
+
console.log(`AA large text / UI (>= 3:1): ${verdict(3)}`)
|
package/templates/AGENTS.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
> このファイルと `agents/*.md` は、いずれも **Vantage フレームワークが所有する正本**の
|
|
8
8
|
> コピーです。手で書き換えても、`vantage upgrade` を実行するとフレームワーク同梱の正本から
|
|
9
9
|
> 再同期されて上書きされます。アプリ固有のメモは別ファイル(例: `README.md`)に書いてください。
|
|
10
|
+
> 例外はプロジェクトルートの `DESIGN.md` で、これは**ユーザーが所有**します(`vantage upgrade` も
|
|
11
|
+
> `vantage add agents` も触らない。→「デザインの意図(DESIGN.md)」)。
|
|
10
12
|
>
|
|
11
13
|
> 手順を伴う踏み込んだワークフローは、同梱の Claude Code Skill に分かれています。このファイルは
|
|
12
14
|
> 「地図」、`agents/*.md` は「種類ごとの静的リファレンス」、Skill は「手順書」という役割分担です。
|
|
@@ -94,6 +96,7 @@ root/
|
|
|
94
96
|
| `@squadbase/vantage/components` | 複合パーツ(`PageShell`・`DashboardCardPreset`・`DataTablePreset`・`EChart` ほか) |
|
|
95
97
|
| `@squadbase/vantage/table` | `FilePageView`・`TableViewer`(データファイルページの表ビューア) |
|
|
96
98
|
| `@squadbase/vantage/slide` | `SlideDeck`・`Slide`・`Steps`・`Step`・`MorphElement`・`useSlideNumber`・`useIsActiveSlide`(スライド専用。1920×1080 の固定キャンバス) |
|
|
99
|
+
| `@squadbase/vantage/doc` | `Document`(ドキュメント専用。中の素の HTML 要素に見出し・表などのスタイルが当たる) |
|
|
97
100
|
| `@squadbase/vantage/markdown` | `MarkdownRenderer`(Shiki を隔離するための専用サブパス) |
|
|
98
101
|
| `@squadbase/vantage/server` | `ApiContext`・`ApiHandler`・`HttpError`・`isHttpError`・`json`(server/ 側でのみ使う) |
|
|
99
102
|
|
|
@@ -108,6 +111,18 @@ root/
|
|
|
108
111
|
- `server/` が**無い** → 外部 API を直接叩くなら `useQuery`(→ `agents/page.md`)。自前の API が
|
|
109
112
|
要るようになったら `server/api/*.ts` を足すだけでよい(設定変更は不要)。
|
|
110
113
|
|
|
114
|
+
## デザインの意図(DESIGN.md)
|
|
115
|
+
|
|
116
|
+
プロジェクトルートに `DESIGN.md` があれば、**UI(ページ・スライド・コンポーネント)を書く前に
|
|
117
|
+
読む。** 色・チャート・書体・レイアウトの使い分けがトークン名で書いてあるので、それに従って
|
|
118
|
+
トークンで書く(値は `styles.css` にあり、`DESIGN.md` には色コードを書かない)。
|
|
119
|
+
|
|
120
|
+
- **会話中の指示は `DESIGN.md` より優先する。** 同じ指示が繰り返されたら、`DESIGN.md` への
|
|
121
|
+
反映をユーザーに提案する。
|
|
122
|
+
- **「色を変えて」「ブランドに合わせて」などデザイン全体の変更は、ファイルごとに直さない。**
|
|
123
|
+
Skill `vantage-design` の手順で `DESIGN.md` と `styles.css` をまとめて更新する。
|
|
124
|
+
- `DESIGN.md` はユーザーの持ち物。`vantage upgrade` は書き換えない。
|
|
125
|
+
|
|
111
126
|
## 何を書くか → どのファイルを読むか
|
|
112
127
|
|
|
113
128
|
**書こうとしている種類のファイルだけを開けばよい。** まず該当する 1 ファイルを readFiles で
|
|
@@ -118,6 +133,7 @@ root/
|
|
|
118
133
|
| ダッシュボード / 通常ページ(`.tsx`) | `agents/page.md` |
|
|
119
134
|
| API(`server/`) | `agents/api.md` |
|
|
120
135
|
| スライド(`.slide.tsx`) | `agents/slide.md` |
|
|
136
|
+
| ドキュメント(`.doc.tsx`) | `agents/doc.md` |
|
|
121
137
|
| `.xlsx` ページ | `agents/xlsx.md` |
|
|
122
138
|
| `.csv` ページ | `agents/csv.md` |
|
|
123
139
|
|
|
@@ -173,6 +189,7 @@ body・レスポンスの status と形)まで出る。`vantage check --json` /
|
|
|
173
189
|
- **`vantage-app`** — アプリを一から作る / 構成を広げるときの進め方と検証の順序
|
|
174
190
|
- **`vantage-add-feature`** — 既存アプリに page / api / ui を 1 つ足す定型
|
|
175
191
|
- **`vantage-slide`** — `.slide.tsx` でスライドデッキを書く(キャンバスの予算・段階表示・pptx 書き出し)
|
|
192
|
+
- **`vantage-design`** — `DESIGN.md` と `styles.css` をまとめて作る / 直す(配色・書体・ブランド合わせ)
|
|
176
193
|
- **`vantage-pitfalls`** — Base UI(≠ Radix)の癖など、静かに壊れる落とし穴のリファレンス
|
|
177
194
|
- **`project-storage`** — Squadbase の Project Storage(アップロード済みファイル)をブラウザから読み書きする
|
|
178
195
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# ドキュメント(.doc.tsx)
|
|
2
|
+
|
|
3
|
+
フレームワーク所有の知識ファイルで、`vantage upgrade` で再同期されます。`.doc.tsx` で
|
|
4
|
+
ドキュメントを書くときに読んでください。不変条件・ディレクトリ構造は `AGENTS.md` を
|
|
5
|
+
先に読んでいる想定です。
|
|
6
|
+
|
|
7
|
+
## ドキュメントは `.doc.tsx` で書く
|
|
8
|
+
|
|
9
|
+
`src/june-summary.doc.tsx` → `/june-summary`。上から下へ読む文章のページで、表やチャートを
|
|
10
|
+
文中に置けます。中身は `<Document>` を返す普通の React コンポーネントで、`definePage` もナビも
|
|
11
|
+
通常のページと同じように効きます。
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { definePage } from "@squadbase/vantage"
|
|
15
|
+
import { EChart } from "@squadbase/vantage/components"
|
|
16
|
+
import { Document } from "@squadbase/vantage/doc"
|
|
17
|
+
|
|
18
|
+
export const page = definePage({ title: "6月度サマリー", navLabel: "6月度サマリー" })
|
|
19
|
+
export default function JuneSummary() {
|
|
20
|
+
return (
|
|
21
|
+
<Document>
|
|
22
|
+
<h1>6月度サマリー</h1>
|
|
23
|
+
<p>6月の売上は <strong>5,250 万円</strong>で、目標を 5% 上回りました。</p>
|
|
24
|
+
<h2>週次の売上</h2>
|
|
25
|
+
<figure>
|
|
26
|
+
<EChart option={option} height={280} ariaLabel="6月の週次売上" />
|
|
27
|
+
<figcaption>第4週はキャンペーン初週</figcaption>
|
|
28
|
+
</figure>
|
|
29
|
+
<table>…</table>
|
|
30
|
+
</Document>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 書き方
|
|
36
|
+
|
|
37
|
+
- **素の HTML 要素で書く。** `<Document>` の中の `h1`〜`h4`・`p`・`ul`/`ol`/`li`・`table`・
|
|
38
|
+
`blockquote`・`pre`/`code`・`hr`・`a`・`figure`/`figcaption`・`img` には、見出しの大きさ・余白・
|
|
39
|
+
罫線などが最初から当たっています。クラスは要りません。
|
|
40
|
+
- **Tailwind のユーティリティは、その要素だけ見た目を変えたいときに使う。** 要素の既定の
|
|
41
|
+
スタイルはユーティリティより弱いので、`className` を付ければそちらが勝ちます。ドキュメント全体の
|
|
42
|
+
見た目を変えたいときはユーティリティを並べず、下の `--doc-*` を変えます。
|
|
43
|
+
- **数値はコードに直接書く。** ドキュメントは書いた時点の内容を残すページです。
|
|
44
|
+
`useApiQuery` などで読み込むと、開くたびに値が変わります。
|
|
45
|
+
- **チャートは `EChart`(`@squadbase/vantage/components`)を文中に置く。** `figure` で囲めば
|
|
46
|
+
`figcaption` がキャプションになります。
|
|
47
|
+
- **ページ全体を包むのは `<Document>` だけ。** `PageShell` などのダッシュボード用の枠で包まない
|
|
48
|
+
(本文の幅と余白は `<Document>` が決めます)。
|
|
49
|
+
|
|
50
|
+
## 見た目を変える
|
|
51
|
+
|
|
52
|
+
配色・書体・本文の幅は `--doc-*` の CSS 変数です。既定値はアプリのトークンへの別名なので、
|
|
53
|
+
ダークモードにもそのまま追従します。
|
|
54
|
+
|
|
55
|
+
| 変数 | 既定値 | 何に効くか |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `--doc-fg` | `var(--foreground)` | 本文の文字色 |
|
|
58
|
+
| `--doc-muted` | `var(--muted-foreground)` | 引用・キャプション |
|
|
59
|
+
| `--doc-accent` | `var(--primary)` | リンク |
|
|
60
|
+
| `--doc-border` | `var(--border)` | 表・`h2` の下線・引用・`hr` |
|
|
61
|
+
| `--doc-subtle` | `var(--muted)` | コード・表の見出し行の背景 |
|
|
62
|
+
| `--doc-font-body` / `--doc-font-heading` / `--doc-font-mono` | アプリの書体 | 本文 / 見出し / コード |
|
|
63
|
+
| `--doc-size-body` | `1rem` | 本文の文字サイズ(見出しはこれに比例) |
|
|
64
|
+
| `--doc-line-height` | `1.8` | 本文の行間 |
|
|
65
|
+
| `--doc-max-width` | `48rem` | 本文の幅 |
|
|
66
|
+
|
|
67
|
+
アプリのすべてのドキュメントに効かせるなら `styles.css` の `:root` で定義し直します。1 つの
|
|
68
|
+
ドキュメントだけなら `<Document theme={{ accent: "#2563eb", maxWidth: "56rem" }}>` のように
|
|
69
|
+
`theme` で渡します(`theme` のキーは変数名から `--doc-` を外してキャメルケースにしたもの)。
|
|
70
|
+
|
|
71
|
+
`.doc` を付けられるのはルートになるページモジュールだけで、`_layout.doc.tsx` などは
|
|
72
|
+
`INVALID_PAGE_VARIANT` エラーになります。`june.doc.tsx` と `june.tsx` は同じ URL に解決するので
|
|
73
|
+
`ROUTE_CONFLICT` です。
|