@squadbase/vantage-template 0.1.1-dev1.7a4f5d9 → 0.1.1-dev1.8858348
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/README.md +12 -2
- package/base-template/.squadbase/skills/vantage-design/SKILL.md +54 -54
- package/base-template/.squadbase/skills/vantage-design/references/extract.md +26 -27
- package/base-template/.squadbase/skills/vantage-design/references/format.md +12 -172
- package/base-template/.squadbase/skills/vantage-design/references/presets.md +50 -110
- package/base-template/.squadbase/skills/vantage-pitfalls/SKILL.md +5 -0
- package/base-template/.squadbase/skills/vantage-slide/SKILL.md +54 -36
- package/base-template/AGENTS.md +43 -16
- package/base-template/agents/doc.md +48 -0
- package/base-template/agents/page.md +23 -2
- package/base-template/agents/slide.md +77 -3
- package/base-template/bun.lock +4 -4
- package/base-template/package.json +2 -2
- package/base-template/src/_layout.tsx +7 -0
- package/base-template/src/components/user-card.tsx +1 -1
- package/base-template/src/index.tsx +1 -1
- package/base-template/src/styles.css +105 -20
- package/dist/index.js +956 -0
- package/package.json +6 -3
- package/base-template/DESIGN.md +0 -108
|
@@ -1,110 +1,50 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
- `--primary`
|
|
51
|
-
|
|
52
|
-
```css
|
|
53
|
-
:root {
|
|
54
|
-
--primary: var(--color-sky-700);
|
|
55
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
56
|
-
}
|
|
57
|
-
.dark,
|
|
58
|
-
[data-theme="dark"] {
|
|
59
|
-
--primary: var(--color-sky-300);
|
|
60
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
- `DESIGN.md` の差分: 「全体のトーン」を上の文に。チャートの色味を「スカイ → シアン → インディゴ →
|
|
65
|
-
ティール → スレート」に。良い = `--chart-4`(ティール)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
66
|
-
禁止: `--chart-1` と `--chart-2` を隣り合う細い線で並べる(どちらも明るい青系)。
|
|
67
|
-
|
|
68
|
-
## `vivid`
|
|
69
|
-
|
|
70
|
-
- トーン: 明るく勢いのある暖色。KPI とトレンドを大きく見せ、強調色をはっきり使う。
|
|
71
|
-
- チャート: `sunset`(オレンジ → アンバー → ローズ → イエロー → ストーン)。
|
|
72
|
-
- `--primary`(オレンジ 600 は白文字で 4.5:1 に届かないので 700 を使う):
|
|
73
|
-
|
|
74
|
-
```css
|
|
75
|
-
:root {
|
|
76
|
-
--primary: var(--color-orange-700);
|
|
77
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
78
|
-
}
|
|
79
|
-
.dark,
|
|
80
|
-
[data-theme="dark"] {
|
|
81
|
-
--primary: var(--color-orange-400);
|
|
82
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
- `DESIGN.md` の差分: トーンを上の文に。主色の行を「濃いオレンジ」に。良い = 専用色なし(▲ と
|
|
87
|
-
`--foreground`)、悪い = `--destructive`。禁止: `--chart-3`(ローズ)と `--destructive` を同じ
|
|
88
|
-
チャートに置く(悪い値と区別できない)。1 系列の強調は `--chart-1` + 残り `--chart-5`。
|
|
89
|
-
|
|
90
|
-
## `mono`
|
|
91
|
-
|
|
92
|
-
- トーン: 白黒と灰色だけ。色で意味を運ばず、太さ・順番・ラベルで読ませる。
|
|
93
|
-
- チャート: `mono`(ジンク 900 → 200。ダークでは反転)。
|
|
94
|
-
- `--primary`(チャートの両端と同じジンク):
|
|
95
|
-
|
|
96
|
-
```css
|
|
97
|
-
:root {
|
|
98
|
-
--primary: var(--color-zinc-900);
|
|
99
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
100
|
-
}
|
|
101
|
-
.dark,
|
|
102
|
-
[data-theme="dark"] {
|
|
103
|
-
--primary: var(--color-zinc-200);
|
|
104
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
- `DESIGN.md` の差分: トーンを上の文に。強調 = `--chart-1`(最も濃い灰)。良い = 専用色なし(▲ と
|
|
109
|
-
符号)、悪い = `--destructive`(**画面で唯一の有彩色**として使う)。チャートは系列を 3 つまでにし、
|
|
110
|
-
それ以上は直接ラベルを付ける。禁止: 隣り合う `--chart-4` と `--chart-5`(明度差が小さい)。
|
|
1
|
+
# 初期デザイン(テーマ)
|
|
2
|
+
|
|
3
|
+
プロジェクトの見た目の出発点は、SquadKit の 7 テーマから選ぶ。**テーマ id はプロジェクト作成の
|
|
4
|
+
ワークフローが参照するので変えないこと。** テーマは主色・背景・文字・境界・チャート 5 色・角丸・書体を
|
|
5
|
+
まとめて持つ(ライトとダークの両方)。
|
|
6
|
+
|
|
7
|
+
| id | トーン | 向く場面 |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `neutral` | 既定。Vantage の素の見た目(青の主色と無彩色の面) | 迷ったとき・おまかせ |
|
|
10
|
+
| `ocean` | 青を基調にした落ち着いた信頼感。角丸はやや小さめ | 報告書・経営向け |
|
|
11
|
+
| `forest` | 緑を基調にした自然な印象。丸ゴシック系の書体、角丸はやや小さめ | 環境・ヘルスケア・自然 |
|
|
12
|
+
| `sunset` | 橙を基調にした温かみ。角丸はやや大きめ | 営業・マーケティング |
|
|
13
|
+
| `violet` | 紫を基調にしたやわらかい印象。角丸は大きめ | 華やかさ・ポップ |
|
|
14
|
+
| `rose` | 赤紫からピンクの落ち着いた色。角丸は大きめ(`--destructive` の赤とは別の色) | 華やかさ・ポップ |
|
|
15
|
+
| `mono` | 無彩色寄り。チャートも彩度を抑え、角丸は最小。等幅フォント | 印刷・資料への貼り付け |
|
|
16
|
+
|
|
17
|
+
## 当てる
|
|
18
|
+
|
|
19
|
+
プロジェクトルートで次を実行する。`--dry-run` で書き込まずに結果を見られる。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @squadbase/vantage-template theme <id>
|
|
23
|
+
npx @squadbase/vantage-template theme ocean --reset-chart # chart コマンドで選んだ配色を捨て、テーマのチャート色に揃える
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `styles.css` の ``/* squadkit-theme — regenerated by `theme`; edits here are lost */`` 〜
|
|
27
|
+
`/* squadkit-theme:end */` の範囲(テーマ範囲)だけを差し替える。**範囲の中は手で編集しない**。
|
|
28
|
+
マーカーが無いファイルには自動で足される。同じ id を再実行しても変わらない。
|
|
29
|
+
- テーマ範囲はファイル先頭の `:root` より後ろに置かれ、同じ詳細度なら後ろが勝つ。
|
|
30
|
+
先頭の `:root` に手書きした `--primary` などはテーマに負ける。
|
|
31
|
+
- `chart <preset>` の範囲(`--chart-*` だけ)はテーマ範囲の**後ろ**に置かれ、テーマのチャート色に勝つ。
|
|
32
|
+
チャートの配色もテーマに任せるなら `--reset-chart` で外す。
|
|
33
|
+
|
|
34
|
+
## 旧プリセット id の読み替え
|
|
35
|
+
|
|
36
|
+
古い呼び出しの `default` / `calm` / `vivid` / `mono` は、`theme` コマンドがそのまま受けて次の id として扱う。
|
|
37
|
+
|
|
38
|
+
| 旧 | 新 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `default` | `neutral` |
|
|
41
|
+
| `calm` | `ocean` |
|
|
42
|
+
| `vivid` | `sunset` |
|
|
43
|
+
| `mono` | `mono` |
|
|
44
|
+
|
|
45
|
+
## テーマに無い値(ブランド色など)
|
|
46
|
+
|
|
47
|
+
テーマの `--primary` を変えたい、特定の色だけブランドに合わせたい、というときは、テーマを当てたうえで
|
|
48
|
+
**`/* squadkit-theme:end */`(チャート範囲があればその終端)より後ろ**に、変えたいトークンだけ
|
|
49
|
+
`:root` と `.dark, [data-theme="dark"]` の**両方**に書く。前に書くとテーマに負ける。
|
|
50
|
+
`scripts/contrast.mjs` で `--primary-foreground` / `--primary` をライトとダークで確かめる。
|
|
@@ -94,6 +94,11 @@ Base UI の `SelectValue` は選択中の **value をそのまま描き**、`Sel
|
|
|
94
94
|
- 表示ルート `/sales/:customerId`
|
|
95
95
|
- リンク `to="/sales/$customerId"` + `params={{ customerId }}` / 取り出し `useParams().customerId`
|
|
96
96
|
|
|
97
|
+
## 日本語アプリは `lang` を指定する
|
|
98
|
+
|
|
99
|
+
ルート `src/_layout.tsx` に `export const lang = "ja"`(リテラル)が無いと `<html lang="en">` のままで、
|
|
100
|
+
スライドの見出しが文節の途中で折れる。内容が日本語なら必ず指定する。
|
|
101
|
+
|
|
97
102
|
## ページ:`definePage` の値はリテラルで書く
|
|
98
103
|
|
|
99
104
|
title/description/navLabel は**ビルド時に静的抽出**される。変数・関数呼び出し・テンプレート補間を
|
|
@@ -43,9 +43,8 @@ export default function JuneDeck() {
|
|
|
43
43
|
|
|
44
44
|
- **1 ファイル = 1 デッキ = 1 ルート。** `export default` は `<SlideDeck>` を返す React コンポーネント
|
|
45
45
|
(通常のページと同じ契約なので、`vantage check` も `vantage routes` も特別扱いをしません)。
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
テンプレート補間は不可)。ナビの表示名はこれで決まります。
|
|
46
|
+
- **ファイル形式の MUST / SHOULD(`<Slide>` は `<SlideDeck>` の直下、`<Step>` は `<Steps>` の直下、
|
|
47
|
+
`definePage` はリテラル など)は `agents/slide.md` と `agents/page.md` が正本**です。ここでは繰り返しません。
|
|
49
48
|
- **`.slide` を付けられるのはルートになるページモジュールだけ。** `_layout.slide.tsx` や
|
|
50
49
|
`deck.slide.ts` は `INVALID_PAGE_VARIANT` エラーになります。
|
|
51
50
|
- **`june.slide.tsx` と `june.tsx` は同じ URL** になるので `ROUTE_CONFLICT` です。どちらかを消すこと。
|
|
@@ -56,10 +55,24 @@ export default function JuneDeck() {
|
|
|
56
55
|
スライド専用のコンポーネントを `components/` に切り出すと、デッキ 1 本を読むのに 2 ファイル
|
|
57
56
|
追わせることになります。
|
|
58
57
|
|
|
58
|
+
## まず block を探す
|
|
59
|
+
|
|
60
|
+
1 枚分の中身は、手で組む前に `@squadbase/vantage/slide` の block(`SlideCover` `SlideExecSummary`
|
|
61
|
+
`SlideKpiHero` `SlideKpiGrid` `SlideChartInsight` `SlideScorecardTable` `SlideNextActions` `SlideSection` `SlideComparison` `SlideChartFull`)に
|
|
62
|
+
合うものがないか探します。`<Slide>` の**中**に置き、props は `vantage docs <name>`(例:
|
|
63
|
+
`vantage docs slide-cover`)で引く。一覧は `agents/slide.md` が正本です。
|
|
64
|
+
- props は block 間で共通: `value: number | null` + `format`(上書きだけ `display`)、`delta: { value, format? }` + `betterWhen` + `comparisonLabel`、`target: number`、`source` は文字列、`asOf` は日付だけ(「時点」は block が付ける)。
|
|
65
|
+
|
|
66
|
+
- block は `@squadbase/vantage/slide` から import する。**新しい import 元は増えない**(下の
|
|
67
|
+
「import してよいもの」と矛盾しない)。`vantage add` でコピーするものでもない。
|
|
68
|
+
- block が合わない**1 枚だけ**を、この下の規約で手書きする。デッキ全体を手書きに切り替えない。
|
|
69
|
+
- デッキ以外のファイルは作らない。block を使っても、デッキは 1 ファイルのままで、独自の
|
|
70
|
+
ヘルパーコンポーネントは同じ `.slide.tsx` に書く。
|
|
71
|
+
|
|
59
72
|
## import してよいもの
|
|
60
73
|
|
|
61
74
|
- `@squadbase/vantage/slide` — `SlideDeck` `Slide` `Steps` `Step` `MorphElement` `useSlideNumber`
|
|
62
|
-
`useIsActiveSlide` `SlideCanvas`
|
|
75
|
+
`useIsActiveSlide` `SlideCanvas`、1 枚分の block(`SlideCover` ほか上の 10 個)、手書きの 1 枚に使う部品(`SlideHeading` `SlideSourceLine` `SlideColumns` `SlideColumn` `DeltaText`)と、その型
|
|
63
76
|
- `@squadbase/vantage` — `definePage`
|
|
64
77
|
- `@squadbase/vantage/components` の `EChart` — **チャートを載せるときはこれ**(→「チャート」)
|
|
65
78
|
- `lucide-react` のアイコン
|
|
@@ -77,21 +90,25 @@ export default function JuneDeck() {
|
|
|
77
90
|
- 各スライドのルート要素はキャンバスを埋める(`width: "100%"; height: "100%"`)
|
|
78
91
|
- インライン `style={{ … }}` を使う。読み込んだ CSS はグローバルです
|
|
79
92
|
|
|
80
|
-
|
|
93
|
+
以下の値がスライドの規約です。ヒーローと本文は `var(--slide-size-hero)` /
|
|
94
|
+
`var(--slide-size-body)` としても読めます(→ `references/tokens.md`)。
|
|
95
|
+
|
|
96
|
+
### タイプスケール
|
|
81
97
|
|
|
82
98
|
| 要素 | サイズ |
|
|
83
99
|
| --- | --- |
|
|
84
|
-
| ヒーロータイトル |
|
|
85
|
-
| セクション見出し |
|
|
86
|
-
| ページ見出し |
|
|
87
|
-
| 本文 |
|
|
88
|
-
| キャプション / ラベル |
|
|
100
|
+
| ヒーロータイトル | 168px |
|
|
101
|
+
| セクション見出し | 88px |
|
|
102
|
+
| ページ見出し | 64px |
|
|
103
|
+
| 本文 | 36px |
|
|
104
|
+
| キャプション / ラベル | 24px |
|
|
89
105
|
|
|
90
|
-
###
|
|
106
|
+
### 余白とグリッド
|
|
91
107
|
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
108
|
+
- セーフエリア: キャンバス端から **左右 160px・上下 120px**。中身はこの内側の **1600 × 840px** に置き、文字を端に触れさせない
|
|
109
|
+
- グリッド: 内容幅 1600px を **12 列**(列幅 104px・溝 32px)に割る
|
|
110
|
+
- line-height: 見出し 1.2、本文 1.6
|
|
111
|
+
- 要素間: 32 / 48 / 64px のどれか
|
|
95
112
|
|
|
96
113
|
### 縦方向の予算 — 中身は 1080px に収まらなければならない
|
|
97
114
|
|
|
@@ -99,33 +116,32 @@ export default function JuneDeck() {
|
|
|
99
116
|
計算して収まることを確かめること。**これがスライドが壊れる原因の第 1 位**で、確かめない限り
|
|
100
117
|
溢れていると思ってください。
|
|
101
118
|
|
|
102
|
-
**使える高さ** = `1080 −
|
|
103
|
-
先に padding を決めて、その予算の中で設計します。
|
|
119
|
+
**使える高さ** = `1080 − 上下のセーフエリア(120px × 2)` = **840px**。この予算の中で設計します。
|
|
104
120
|
|
|
105
121
|
**要素の高さ** = `文字サイズ × line-height × 行数`。2 行に折り返す箇条書きは 2 行と数えます。
|
|
106
|
-
次の要素を足す前に、その下の gap(32
|
|
122
|
+
次の要素を足す前に、その下の gap(32 / 48 / 64px)を加算してください。
|
|
107
123
|
|
|
108
|
-
**計算例 — 本文 1
|
|
124
|
+
**計算例 — 本文 1 枚(予算 840px):**
|
|
109
125
|
|
|
110
126
|
| 要素 | 高さ |
|
|
111
127
|
| --- | --- |
|
|
112
|
-
|
|
|
128
|
+
| ページ見出し: 64px × 1.2 × 1 行 | 76.8px |
|
|
113
129
|
| gap | 64px |
|
|
114
|
-
| 本文:
|
|
130
|
+
| 本文: 36px × 1.6 × 3 行 | 172.8px |
|
|
115
131
|
| gap | 48px |
|
|
116
|
-
| 箇条書き 5 行:
|
|
117
|
-
| 箇条書き間の gap 4 つ:
|
|
118
|
-
| **合計** | **
|
|
132
|
+
| 箇条書き 5 行: 36px × 1.6 × 1 行 | 288px(5 × 57.6px) |
|
|
133
|
+
| 箇条書き間の gap 4 つ: 32px | 128px |
|
|
134
|
+
| **合計** | **777.6px ✅ 840 に収まる** |
|
|
119
135
|
|
|
120
|
-
|
|
136
|
+
箇条書きを 6 つにすると 867.2px で溢れます。**書く前に毎ページこの検算をすること。**
|
|
121
137
|
|
|
122
138
|
**ページ単位の規則:**
|
|
123
139
|
|
|
124
140
|
- 「見出し + 本文」か「見出し + 5 つ以内の短い箇条書き」のどちらか。両方は載せない
|
|
125
141
|
- 箇条書きは選んだ文字サイズで 1 行に収まること。折り返すなら短くするか別ページに割る
|
|
126
|
-
- ヒーロータイトル(
|
|
127
|
-
- セクション見出し(
|
|
128
|
-
-
|
|
142
|
+
- ヒーロータイトル(168px)はタイトル + サブタイトル 1 行 + アイブロウまで。それ以外は載せない
|
|
143
|
+
- セクション見出し(88px)のページにはほとんど何も足さない
|
|
144
|
+
- 収めるためにセーフエリアを削る・タイプスケールより小さい文字にする・本文の line-height を 1.6 未満に
|
|
129
145
|
詰める、をやりたくなったら**ページを 2 枚に割る**。予算が厳しいときは分割が常に正解
|
|
130
146
|
|
|
131
147
|
**`overflow: auto/scroll`・負のマージン・transform で溢れを隠さないこと。** キャンバスは固定で、
|
|
@@ -139,7 +155,7 @@ export default function JuneDeck() {
|
|
|
139
155
|
それ以外はプレーンな const にする(→ `references/tokens.md`)
|
|
140
156
|
- **書体** — ディスプレイ 1 + 本文 1。指定がなければシステムスタック。見出しは太く(800–900)、
|
|
141
157
|
本文は通常(400–500)
|
|
142
|
-
- **レイアウトグリッド** —
|
|
158
|
+
- **レイアウトグリッド** — セーフエリアと 12 列グリッド(→「余白とグリッド」)を全ページで貫く。左揃えは編集的、中央揃えは儀礼的
|
|
143
159
|
- **美学のコミットメント** — 1 つ選ぶ: ミニマル / マキシマル / エディトリアル / レトロ /
|
|
144
160
|
ブルータリスト / ソフト・パステル / ネオン / 紙・印刷。混ぜない
|
|
145
161
|
|
|
@@ -152,12 +168,12 @@ export default function JuneDeck() {
|
|
|
152
168
|
// ✅ 各カードが独自の JSX ノードを持つ
|
|
153
169
|
const Card = ({ label, value }: { label: string; value: string }) => (
|
|
154
170
|
<div style={{ flex: 1 }}>
|
|
155
|
-
<div style={{ fontSize:
|
|
156
|
-
<div style={{ fontSize:
|
|
171
|
+
<div style={{ fontSize: 24, opacity: 0.6 }}>{label}</div>
|
|
172
|
+
<div style={{ fontSize: 88, fontWeight: 800 }}>{value}</div>
|
|
157
173
|
</div>
|
|
158
174
|
)
|
|
159
175
|
|
|
160
|
-
<div style={{ display: "flex", gap:
|
|
176
|
+
<div style={{ display: "flex", gap: 64 }}>
|
|
161
177
|
<Card label="売上" value="¥5.2億" />
|
|
162
178
|
<Card label="解約率" value="1.4%" />
|
|
163
179
|
</div>
|
|
@@ -169,6 +185,8 @@ const Card = ({ label, value }: { label: string; value: string }) => (
|
|
|
169
185
|
|
|
170
186
|
これは**視覚要素が繰り返すとき**の話で、データが繰り返すときの話ではありません。純粋な
|
|
171
187
|
テキストの箇条書き(`<ul><li>`)は各 `<li>` が既に独立した JSX ノードなので、そのままで正しい。
|
|
188
|
+
`<SlideDeck>` の直下に `<Slide>` を配列で渡すこと自体はファイル形式として可能です(`agents/slide.md`)が、
|
|
189
|
+
1 枚ごとの文言・図を変えるスライドは 1 枚ずつ書きます。
|
|
172
190
|
|
|
173
191
|
## ページ番号
|
|
174
192
|
|
|
@@ -250,8 +268,8 @@ pptx 書き出しのために描き終わりを待たせる必要があります
|
|
|
250
268
|
- [ ] `export default` が `<SlideDeck>` を返している
|
|
251
269
|
- [ ] `<Slide>` が `<SlideDeck>` の直下にある
|
|
252
270
|
- [ ] 各スライドのルート要素が `100% × 100%` を埋めている
|
|
253
|
-
- [ ]
|
|
254
|
-
- [ ] **全ページで(文字サイズ × line-height × 行数)+ gap
|
|
271
|
+
- [ ] 文字がセーフエリア(左右 160px・上下 120px)の内側にある
|
|
272
|
+
- [ ] **全ページで(文字サイズ × line-height × 行数)+ gap ≤ 840px。** 際どいなら分割
|
|
255
273
|
- [ ] 箇条書きが 2 行目に折り返していない
|
|
256
274
|
- [ ] 配色とタイプスケールが全ページで一貫している
|
|
257
275
|
- [ ] 1 ページ 1 メッセージ
|
|
@@ -267,11 +285,11 @@ pptx 書き出しのために描き終わりを待たせる必要があります
|
|
|
267
285
|
## アンチパターン
|
|
268
286
|
|
|
269
287
|
- ❌ 文字の壁。1 ページ 40 語を超えたら分割する
|
|
270
|
-
- ❌
|
|
288
|
+
- ❌ キャンバス全面を本文で使う。セーフエリア(左右 160px・上下 120px)を守る
|
|
271
289
|
- ❌ 縦に 1080px を溢れさせる。切れた中身は見えない — 分割する
|
|
272
290
|
- ❌ `overflow: auto` / `scroll` / `hidden` で溢れを「隠す」。バグを隠しただけ
|
|
273
|
-
- ❌
|
|
274
|
-
- ❌
|
|
291
|
+
- ❌ 詰め込むためにタイプスケールより小さい文字にする・セーフエリアを削る
|
|
292
|
+
- ❌ 本文を 36px 未満にする。プロジェクタで読めない
|
|
275
293
|
- ❌ `@squadbase/vantage/ui` のプリミティブをスライドに置く(縮小されて読めなくなる)
|
|
276
294
|
- ❌ 依存を追加する。使えるのは `@squadbase/vantage/*` と `lucide-react` と標準 Web API だけ
|
|
277
295
|
- ❌ スライド用のコンポーネントを別ファイルに切り出す
|
package/base-template/AGENTS.md
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
> このファイルと `agents/*.md` は、いずれも **Vantage フレームワークが所有する正本**の
|
|
8
8
|
> コピーです。手で書き換えても、`vantage upgrade` を実行するとフレームワーク同梱の正本から
|
|
9
9
|
> 再同期されて上書きされます。アプリ固有のメモは別ファイル(例: `README.md`)に書いてください。
|
|
10
|
-
>
|
|
11
|
-
> `vantage add agents`
|
|
10
|
+
> 例外はプロジェクトルートの任意の `DESIGN.md` で、これは**ユーザーが所有**します(`vantage upgrade` も
|
|
11
|
+
> `vantage add agents` も触らない。→「見た目の規約」)。
|
|
12
12
|
>
|
|
13
13
|
> 手順を伴う踏み込んだワークフローは、同梱の Claude Code Skill に分かれています。このファイルは
|
|
14
14
|
> 「地図」、`agents/*.md` は「種類ごとの静的リファレンス」、Skill は「手順書」という役割分担です。
|
|
@@ -47,6 +47,9 @@ UI キット・開発サーバー・API サーバー・ビルドはすべて Van
|
|
|
47
47
|
- **`definePage` の値はリテラルで書く。** title/description/navLabel はビルド時に静的抽出される
|
|
48
48
|
ため、変数・関数呼び出し・テンプレート補間は使わない。`page` エクスポートはランタイムでは
|
|
49
49
|
読まれない。
|
|
50
|
+
- **アプリの表示言語は、ルート `_layout.tsx` の `export const lang = "en"`(リテラル。BCP 47)で指定する。**
|
|
51
|
+
`<html lang>` になり、日本語の文節改行とスライドの文言切り替えに効く。未指定は `"en"`。
|
|
52
|
+
画面の文言・docs・コメントは、ユーザーが使う言語に合わせる(`lang` もその言語にする)。
|
|
50
53
|
|
|
51
54
|
## ディレクトリ構造(ページをどこに置くか)
|
|
52
55
|
|
|
@@ -95,12 +98,12 @@ root/
|
|
|
95
98
|
| `@squadbase/vantage/ui` | shadcn/ui(Base UI バリアント)プリミティブ(`Button`・`Loading`・`ErrorState`・`Empty` ほか) |
|
|
96
99
|
| `@squadbase/vantage/components` | 複合パーツ(`PageShell`・`DashboardCardPreset`・`DataTablePreset`、KPI の `KpiCard`・`Delta`、型付きチャート `LineChart`・`BarChart`・`AreaChart`・`DonutChart`・`BarList` ほか、`EChart`、書式の `formatValue`) |
|
|
97
100
|
| `@squadbase/vantage/table` | `FilePageView`・`TableViewer`(データファイルページの表ビューア) |
|
|
98
|
-
| `@squadbase/vantage/slide` | `SlideDeck`・`Slide`・`Steps`・`Step`・`MorphElement`・`useSlideNumber`・`useIsActiveSlide`(スライド専用。1920×1080 の固定キャンバス) |
|
|
99
|
-
| `@squadbase/vantage/doc` | `Document`(ドキュメント専用。中の素の HTML 要素に見出し・表などのスタイルが当たる) |
|
|
101
|
+
| `@squadbase/vantage/slide` | `SlideDeck`・`Slide`・`Steps`・`Step`・`MorphElement`・`useSlideNumber`・`useIsActiveSlide`、1 枚分の block `SlideCover`・`SlideExecSummary`・`SlideKpiHero`・`SlideKpiGrid`・`SlideChartInsight`・`SlideScorecardTable`・`SlideNextActions`・`SlideSection`・`SlideComparison`・`SlideChartFull`、手書きの 1 枚に使う部品 `SlideHeading`・`SlideSourceLine`・`SlideColumns`・`SlideColumn`・`DeltaText`(スライド専用。1920×1080 の固定キャンバス) |
|
|
102
|
+
| `@squadbase/vantage/doc` | `Document`、ドキュメント用の block `DocReportHeader`・`DocExecutiveSummary`・`DocKpiScorecard`・`DocFigure`・`DocDataTable`・`DocCallout`・`DocKeyFindings`・`DocActionItems`・`DocNotesAndSources`、部品 `DeltaText`(ドキュメント専用。中の素の HTML 要素に見出し・表などのスタイルが当たる) |
|
|
100
103
|
| `@squadbase/vantage/markdown` | `MarkdownRenderer`(Shiki を隔離するための専用サブパス) |
|
|
101
104
|
| `@squadbase/vantage/server` | `ApiContext`・`ApiHandler`・`HttpError`・`isHttpError`・`json`(server/ 側でのみ使う) |
|
|
102
105
|
|
|
103
|
-
**KPI は `KpiCard`、増減は `Delta`(`comparison`
|
|
106
|
+
**KPI は `KpiCard`、増減は `Delta`(`comparison` を渡し、下がって良い指標は `betterWhen="down"`)。** 向き・率・色は値から計算
|
|
104
107
|
されるので手で渡さない。`TrendIndicator` は非推奨(`direction` を手で渡すので値と食い違いうる)。props は
|
|
105
108
|
`vantage docs kpi-card` / `vantage docs delta` を引く。
|
|
106
109
|
|
|
@@ -123,17 +126,30 @@ import { KpiCard, Delta } from "@squadbase/vantage/components";
|
|
|
123
126
|
- `server/` が**無い** → 外部 API を直接叩くなら `useQuery`(→ `agents/page.md`)。自前の API が
|
|
124
127
|
要るようになったら `server/api/*.ts` を足すだけでよい(設定変更は不要)。
|
|
125
128
|
|
|
126
|
-
##
|
|
129
|
+
## 見た目の規約
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
色・書体・角丸などの**値と色の割り当ては、テーマ(`styles.css` の `/* theme: <name> */` マーカー以降の
|
|
132
|
+
上書き)だけが持つ。** ここには値を書かず、使い分けの規則だけを置く。UI(ページ・スライド・
|
|
133
|
+
コンポーネント)はこの規則に従い、色は必ずトークンで指定する(色コード・素のパレットクラスは書かない)。
|
|
131
134
|
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
135
|
+
- **意味トークン:** 良い = `positive`、悪い = `negative`、注意 = `warning`、情報 = `info`、
|
|
136
|
+
中立 = `neutral`。系列色は `chart-1`〜`chart-5` を番号順に使う(5 系列まで。超えるなら「その他」に
|
|
137
|
+
まとめる)。増減の良否は指標の性質(コスト減・解約率減は良い)で決めて
|
|
138
|
+
positive / negative に分け(`KpiCard` / `Delta` の `betterWhen`。下がって良い指標は `betterWhen="down"`)、向きは ▲▼ や符号で表す。
|
|
139
|
+
- **レイアウト:** 内容はカードで包む。順序は KPI → チャート → 表。値が 1 つなら KPI にする
|
|
140
|
+
(1 本の棒グラフにしない)。強調は 1 画面(スライドは 1 枚)に 1 か所。数値には単位と比較対象を添える。
|
|
141
|
+
- **Do:** トークンで色を指定する / 色の意味をアプリ全体でそろえる / チャートのタイトルに結論を書く。
|
|
142
|
+
- **Don't:** 色コードや素のパレットクラスを書く / `dark:` を並べる / 3D・装飾目的のグラデーション・
|
|
143
|
+
円グラフの多用 / 同じチャートで `negative` を普通の系列色に使う。
|
|
144
|
+
- スライド固有の規則は `agents/slide.md`。
|
|
145
|
+
|
|
146
|
+
**任意の `DESIGN.md`:** プロジェクトルートにあれば読んで従う(密度・スライドの見出し方針・
|
|
147
|
+
ブランド素材などユーザー固有の意図)。AGENTS.md の規則に加えて従うが、**色の割り当てはテーマを優先**
|
|
148
|
+
する。新規には作らない。ユーザーの持ち物で、`vantage upgrade` は書き換えも削除もしない。
|
|
149
|
+
|
|
150
|
+
**デザイン変更の依頼**(「もっと落ち着いた色に」「ブランドに合わせて」など)は、ファイルごとに
|
|
151
|
+
直さず、テーマの切り替えかスタイルシートの上書きで完結させる。`DESIGN.md` には記録しない。今のテーマ名は
|
|
152
|
+
`styles.css` の `/* theme: <name> */` マーカーから読む。手順は Skill `vantage-design`。
|
|
137
153
|
|
|
138
154
|
## 何を書くか → どのファイルを読むか
|
|
139
155
|
|
|
@@ -172,7 +188,7 @@ vantage docs button # 1 ページ表示(短縮名。ui/button に解
|
|
|
172
188
|
vantage docs parts/data-table # 完全な slug でも引ける
|
|
173
189
|
vantage docs data-table --json # { slug, title, description, section, content }
|
|
174
190
|
vantage docs --all # 全ページを連結(まとめて読み込む用)
|
|
175
|
-
vantage docs routing --lang en # 英語版(
|
|
191
|
+
vantage docs routing --lang en # 英語版(`--lang` 省略時は ja。アプリの文言の言語とは無関係)
|
|
176
192
|
```
|
|
177
193
|
|
|
178
194
|
props の表・使用例・落とし穴はコンポーネントのページに載っている。**推測で props を書く前に
|
|
@@ -210,7 +226,7 @@ body・レスポンスの status と形)まで出る。`vantage check --json` /
|
|
|
210
226
|
- **`vantage-app`** — アプリを一から作る / 構成を広げるときの進め方と検証の順序
|
|
211
227
|
- **`vantage-add-feature`** — 既存アプリに page / api / ui を 1 つ足す定型
|
|
212
228
|
- **`vantage-slide`** — `.slide.tsx` でスライドデッキを書く(キャンバスの予算・段階表示・pptx 書き出し)
|
|
213
|
-
- **`vantage-design`** —
|
|
229
|
+
- **`vantage-design`** — テーマの切り替え・`styles.css` の上書きで見た目を直す(配色・書体・ブランド合わせ)
|
|
214
230
|
- **`vantage-pitfalls`** — Base UI(≠ Radix)の癖など、静かに壊れる落とし穴のリファレンス
|
|
215
231
|
- **`project-storage`** — Squadbase の Project Storage(アップロード済みファイル)をブラウザから読み書きする
|
|
216
232
|
|
|
@@ -509,3 +525,14 @@ function KpiRow({ items }: { items: Kpi[] }) { /* … */ } // 子の部品は
|
|
|
509
525
|
- **値(定数・データ・列定義・小さな関数)は本体より上。** 小文字の関数・hook も値として上に置く。
|
|
510
526
|
- 型は消えるのでどこでもよい。値のそばに置く。
|
|
511
527
|
- 順序だけのために、既に並んでいるファイルを書き換えない。
|
|
528
|
+
|
|
529
|
+
## アプリの表示言語(`lang`)
|
|
530
|
+
|
|
531
|
+
ルートの `src/_layout.tsx` の `export const lang = "en"` が `<html lang>` になる。**アプリの内容の言語に合わせて書き換える**
|
|
532
|
+
(ユーザーが日本語で依頼している・画面の文言が日本語なら `"ja"`)。
|
|
533
|
+
|
|
534
|
+
- `lang` は**リテラル文字列**(BCP 47。`"ja"` / `"en"` / `"ja-JP"`)。変数・テンプレート補間は読まれない。
|
|
535
|
+
- 読まれるのは**ルートの `src/_layout.tsx` だけ**。入れ子の `_layout.tsx` やページには書かない。
|
|
536
|
+
- 日本語アプリで `"en"` のままだと、スライドの文節改行(`word-break: auto-phrase`)が効かず、見出しが単語の途中で折れる。
|
|
537
|
+
スライドのツールバー文言も `lang` で切り替わる(`"ja"` なら日本語、`en*` なら英語)。
|
|
538
|
+
- 値は消さない。指定が無いと `"en"` 扱いになる。
|
|
@@ -15,6 +15,13 @@ import { definePage } from "@squadbase/vantage"
|
|
|
15
15
|
import { BarChart } from "@squadbase/vantage/components"
|
|
16
16
|
import { Document } from "@squadbase/vantage/doc"
|
|
17
17
|
|
|
18
|
+
const weekly = [
|
|
19
|
+
{ week: "第1週", 売上: 1180 },
|
|
20
|
+
{ week: "第2週", 売上: 1240 },
|
|
21
|
+
{ week: "第3週", 売上: 1210 },
|
|
22
|
+
{ week: "第4週", 売上: 1620 },
|
|
23
|
+
]
|
|
24
|
+
|
|
18
25
|
export const page = definePage({ title: "6月度サマリー", navLabel: "6月度サマリー" })
|
|
19
26
|
export default function JuneSummary() {
|
|
20
27
|
return (
|
|
@@ -50,6 +57,30 @@ export default function JuneSummary() {
|
|
|
50
57
|
- **ページ全体を包むのは `<Document>` だけ。** `PageShell` などのダッシュボード用の枠で包まない
|
|
51
58
|
(本文の幅と余白は `<Document>` が決めます)。
|
|
52
59
|
|
|
60
|
+
## まず block を探す
|
|
61
|
+
|
|
62
|
+
1 節分の中身は、手で組む前に `@squadbase/vantage/doc` の block から探します(`<Document>` の直下に
|
|
63
|
+
並べる。多くは 1 block = 1 節。`DocCallout`・`DocFigure`・`DocDataTable` は節ではなく、節の中(本文の間)に置く部品)。props は `vantage docs <name>`(例: `vantage docs doc-kpi-scorecard`)で引く。
|
|
64
|
+
|
|
65
|
+
| block | 用途 |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `DocReportHeader` | レポートの冒頭(タイトル・サブタイトル・対象期間・データ時点・作成者・出典) |
|
|
68
|
+
| `DocExecutiveSummary` | 結論を先に述べる要約の節 |
|
|
69
|
+
| `DocKpiScorecard` | 主要指標をまとめたスコアカード |
|
|
70
|
+
| `DocFigure` | 図表 1 つとキャプション(チャートは children で渡す) |
|
|
71
|
+
| `DocDataTable` | 素の `table` による表 |
|
|
72
|
+
| `DocCallout` | 補足・示唆・注意・決定の囲み(`kind`: `note` / `insight` / `warning` / `decision`) |
|
|
73
|
+
| `DocKeyFindings` | 主要な発見の箇条 |
|
|
74
|
+
| `DocActionItems` | 次のアクション(担当・期限つき) |
|
|
75
|
+
| `DocNotesAndSources` | 末尾の注記・用語の定義・データソースをまとめた節 |
|
|
76
|
+
|
|
77
|
+
**props の渡し方は block 間で共通。** 数値は `value: number | null` と `format`(整形は block がする。表示を上書きするときだけ `display`。`null` は「—」)。前期比などは `delta: { value, format? }` と `comparisonLabel`(例 `"前年同期比"`)、良し悪しは指標ごとの `betterWhen`(`"up"` が既定、コストなど下がるほど良いものは `"down"`。向きは block が符号から出す)。目標は `target: number`。出典は `source`、時点は `asOf` に**日付だけ**(例 `"2026-09-30"`。「データ時点」は block が付けるので「時点」を書かない)。時系列は、単一系列なら `{ x, y }[]`(`trend`)。
|
|
78
|
+
|
|
79
|
+
本文の中で増減を書くときは `DeltaText`(部品。「▲ +3.2%」の形で、文字サイズは持たず置かれた行に従う。`value` `format` `betterWhen` `comparisonLabel`)を使う。節ではなく文の中に置く。
|
|
80
|
+
|
|
81
|
+
block が合わない**1 節だけ**を素の HTML 要素で手で書く。import 元は `@squadbase/vantage/doc` のままで、
|
|
82
|
+
block のための新しい import 元はありません。本文は文字列か ReactNode で渡し、Markdown 文字列は渡さない。
|
|
83
|
+
|
|
53
84
|
## 見た目を変える
|
|
54
85
|
|
|
55
86
|
配色・書体・本文の幅は `--doc-*` の CSS 変数です。既定値はアプリのトークンへの別名なので、
|
|
@@ -74,3 +105,20 @@ export default function JuneSummary() {
|
|
|
74
105
|
`.doc` を付けられるのはルートになるページモジュールだけで、`_layout.doc.tsx` などは
|
|
75
106
|
`INVALID_PAGE_VARIANT` エラーになります。`june.doc.tsx` と `june.tsx` は同じ URL に解決するので
|
|
76
107
|
`ROUTE_CONFLICT` です。
|
|
108
|
+
|
|
109
|
+
## ファイル形式の規約
|
|
110
|
+
|
|
111
|
+
置き場所・URL・default export・`definePage` の書き方は全ページ共通(`agents/page.md` の
|
|
112
|
+
「ページファイルの規約」)。ここではドキュメント固有のものだけを挙げます。
|
|
113
|
+
|
|
114
|
+
**MUST**
|
|
115
|
+
|
|
116
|
+
- ファイル名は `<name>.doc.tsx`(`.jsx` も可)。サフィックスは小文字で 1 つだけ。`.doc.mdx` は
|
|
117
|
+
`INVALID_PAGE_VARIANT`、`.DOC.tsx`・二重サフィックスは黙って通常ページになる
|
|
118
|
+
- default export は `<Document>` をルートに返す。フレームワークは包まない
|
|
119
|
+
- ドキュメントの部品は `@squadbase/vantage/doc` から import する
|
|
120
|
+
|
|
121
|
+
**SHOULD**
|
|
122
|
+
|
|
123
|
+
- `PageShell` で包まない・PDF の保存ボタンを自作しない(上の「書き方」)
|
|
124
|
+
- 数値はコードに直接書き、いつ時点の値かを本文に書く
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
(ダッシュボード)を書くときに読んでください。前提となる不変条件・ディレクトリ構造は
|
|
5
5
|
`AGENTS.md` を先に読んでいる想定です。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
書き始める前に `AGENTS.md` の「見た目の規約」(と、あればプロジェクトルートの `DESIGN.md`)に従う。
|
|
8
8
|
|
|
9
9
|
## 最小アプリ(2 ファイル)
|
|
10
10
|
|
|
@@ -71,6 +71,7 @@ URL になる。各ページは**デフォルトエクスポートの React コ
|
|
|
71
71
|
| `_404.tsx` | Not Found ページ |
|
|
72
72
|
| `_error.tsx` | ルートが throw したときのエラーページ |
|
|
73
73
|
| `monthly-report.slide.tsx` | `/monthly-report`(スライドデッキ。詳しくは `agents/slide.md`) |
|
|
74
|
+
| `june-summary.doc.tsx` | `/june-summary`(ドキュメント。詳しくは `agents/doc.md`) |
|
|
74
75
|
| `sales-export.csv` | `/sales-export`(詳しくは `agents/csv.md`) |
|
|
75
76
|
| `data/june.xlsx` | `/data/june`(詳しくは `agents/xlsx.md`) |
|
|
76
77
|
|
|
@@ -89,6 +90,26 @@ export default function MonthlyAnalysis() {
|
|
|
89
90
|
}
|
|
90
91
|
```
|
|
91
92
|
|
|
93
|
+
### ページファイルの規約(`.tsx` / `.slide.tsx` / `.doc.tsx` 共通)
|
|
94
|
+
|
|
95
|
+
**MUST**
|
|
96
|
+
|
|
97
|
+
- ページルートの配下に置く。`components/` などの走査対象外のディレクトリに置いたファイルはページに
|
|
98
|
+
ならず、エラーも出ない。`_` 始まりの名前は予約名(`_layout` / `_404` / `_error`)にだけ使う
|
|
99
|
+
(それ以外の `_` 始まりはページにならない。予約名にサフィックスを付けると `INVALID_PAGE_VARIANT`)
|
|
100
|
+
- URL はサフィックスと拡張子を除いたパスで決まる。同じ URL になる別ファイル(`june.tsx` /
|
|
101
|
+
`june.slide.tsx` / `june.doc.tsx` / `june.csv`)を並べない(`ROUTE_CONFLICT`)。テンプレートの
|
|
102
|
+
未編集の `index.tsx` だけは例外で、`index.slide.tsx` / `index.doc.tsx` が `/` を取れる
|
|
103
|
+
- default export は React の関数コンポーネント(無いと `MISSING_DEFAULT_EXPORT`。関数かどうかは
|
|
104
|
+
検査されない)
|
|
105
|
+
- `definePage({ ... })` にはオブジェクトリテラルを直接渡し、`title` / `description` / `navLabel` は
|
|
106
|
+
文字列リテラルで書く。ビルド時に静的抽出されるので、変数・関数呼び出し・spread・shorthand・
|
|
107
|
+
`${}` を含むテンプレート文字列は**エラーにならず黙ってメタなし**になる
|
|
108
|
+
|
|
109
|
+
**SHOULD**
|
|
110
|
+
|
|
111
|
+
- `definePage` に `title` と `navLabel` を書く(ナビの表示名とブラウザのタブ名になる)
|
|
112
|
+
|
|
92
113
|
### ナビはルート一覧から組む
|
|
93
114
|
|
|
94
115
|
`useRoutes()` がページルート一覧(スキャン順)を返すので、リンク配列を手で持たない。
|
|
@@ -109,7 +130,7 @@ routes.map((r) => (
|
|
|
109
130
|
```
|
|
110
131
|
|
|
111
132
|
`RouteInfo`: `path`(`/sales/:id`)・`to`(`/sales/$id`)・`params`・`dynamic`・`index`・`label`・
|
|
112
|
-
`title`・`description`・`navLabel`・`kind`(`"module"` | `"file"`)・`variant`(`"slide"`)。
|
|
133
|
+
`title`・`description`・`navLabel`・`kind`(`"module"` | `"file"`)・`variant`(`"slide"` | `"doc"`)。
|
|
113
134
|
後ろの 2 つで、ナビをダッシュボード / スライド / データに分けたりアイコンを変えたりできます。
|
|
114
135
|
|
|
115
136
|
### フィルタ状態は URL に置く
|