@careerchain/stdd 0.1.0

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.
Files changed (53) hide show
  1. package/README.md +44 -0
  2. package/assets/.claude/agents/code-reviewer.md +170 -0
  3. package/assets/.claude/agents/implementer.md +96 -0
  4. package/assets/.claude/agents/plan-writer.md +124 -0
  5. package/assets/.claude/agents/qa-engineer.md +133 -0
  6. package/assets/.claude/agents/spec-reviewer.md +173 -0
  7. package/assets/.claude/agents/spec-writer.md +194 -0
  8. package/assets/.claude/agents/test-reviewer.md +218 -0
  9. package/assets/.claude/docs/spec-driven-development-guide.md +436 -0
  10. package/assets/.claude/hooks/pre-push-check.sh +160 -0
  11. package/assets/.claude/settings.json +67 -0
  12. package/assets/.claude/skills/auto-implement/SKILL.md +168 -0
  13. package/assets/.claude/skills/auto-implement/references/github-project.md +54 -0
  14. package/assets/.claude/skills/auto-implement/references/phases.md +244 -0
  15. package/assets/.claude/skills/create-pr/SKILL.md +112 -0
  16. package/assets/.claude/skills/documenting-plans/SKILL.md +217 -0
  17. package/assets/.claude/skills/documenting-plans/templates/plan.md +182 -0
  18. package/assets/.claude/skills/documenting-specifications/SKILL.md +300 -0
  19. package/assets/.claude/skills/documenting-specifications/guides/error-handling.md +78 -0
  20. package/assets/.claude/skills/documenting-specifications/guides/stdd-violations.md +237 -0
  21. package/assets/.claude/skills/documenting-specifications/templates/requirements.md +184 -0
  22. package/assets/.claude/skills/documenting-specifications/templates/screen-items-definition.md +179 -0
  23. package/assets/.claude/skills/documenting-specifications/templates/tech-design.md +241 -0
  24. package/assets/.claude/skills/generating-wireframes/SKILL.md +121 -0
  25. package/assets/.claude/skills/generating-wireframes/examples/tob-form.html +497 -0
  26. package/assets/.claude/skills/generating-wireframes/examples/tob-list.html +536 -0
  27. package/assets/.claude/skills/generating-wireframes/examples/toc-form.html +493 -0
  28. package/assets/.claude/skills/generating-wireframes/examples/toc-list.html +538 -0
  29. package/assets/.claude/skills/generating-wireframes/guides/from-requirements.md +53 -0
  30. package/assets/.claude/skills/generating-wireframes/templates/index.html +472 -0
  31. package/assets/.claude/skills/generating-wireframes/templates/screen.html +480 -0
  32. package/assets/.claude/skills/introducing-stdd/SKILL.md +185 -0
  33. package/assets/.claude/skills/introducing-stdd/templates/introduction-plan.md +64 -0
  34. package/assets/.claude/skills/kaizen/SKILL.md +129 -0
  35. package/assets/.claude/skills/kaizen/references/code-examples.md +233 -0
  36. package/assets/.claude/skills/reverse-engineering-common-spec/SKILL.md +137 -0
  37. package/assets/.claude/skills/reverse-engineering-feature-spec/SKILL.md +463 -0
  38. package/assets/.claude/skills/reverse-engineering-feature-spec/guides/accuracy.md +215 -0
  39. package/assets/.claude/skills/reverse-engineering-feature-spec/guides/figma-capture.md +313 -0
  40. package/assets/.claude/skills/review-pr-with-agents/SKILL.md +159 -0
  41. package/assets/.claude/skills/searching-existing-solutions/SKILL.md +110 -0
  42. package/assets/.claude/skills/setup-stdd/SKILL.md +82 -0
  43. package/assets/.claude/skills/software-architecture/SKILL.md +260 -0
  44. package/assets/.claude/skills/starting-new-with-stdd/SKILL.md +142 -0
  45. package/assets/.claude/skills/starting-new-with-stdd/templates/bootstrap-plan.md +73 -0
  46. package/assets/.claude/skills/tailoring-spec-format/SKILL.md +103 -0
  47. package/assets/.claude/skills/verifying-consistency/SKILL.md +90 -0
  48. package/assets/stdd.config.yml.tpl +34 -0
  49. package/dist/cli.js +148 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/install.js +121 -0
  52. package/dist/install.js.map +1 -0
  53. package/package.json +48 -0
@@ -0,0 +1,538 @@
1
+ <!-- 汎用サンプル(toC): 検索つき一覧画面。固有名詞なし。 -->
2
+ <!DOCTYPE html>
3
+ <html lang="ja">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>一覧(toC) - ワイヤーフレーム</title>
8
+ <style>
9
+ /*
10
+ * wireframe.css — STDD 汎用ワイヤーフレーム デザインシステム
11
+ *
12
+ * 目的:
13
+ * 低忠実度(low-fidelity)のワイヤーフレームを、技術スタック非依存の
14
+ * 素の HTML + CSS で表現するための共通スタイル。
15
+ *
16
+ * 方針:
17
+ * - グレースケール基調。ブランドカラー・装飾は持たない(実装の自由度を縛らない)。
18
+ * - レイアウト・情報設計・主要文言(タイトル / ボタン / 項目ラベル)の合意形成に用いる。
19
+ * - モバイルファースト。768px 以上でデスクトップレイアウトに展開する。
20
+ * - 各画面 HTML の <head> 内に <style> として直接埋め込む(CSS 単体ファイルは作らない / 自己完結 HTML)。
21
+ *
22
+ * 使い方:
23
+ * components の各クラス(wf-*)を組み合わせて画面を組む。
24
+ * クラス一覧は同ディレクトリの SKILL.md / templates/screen.html を参照。
25
+ */
26
+
27
+ /* ===== Reset / Base ===== */
28
+ * {
29
+ box-sizing: border-box;
30
+ margin: 0;
31
+ padding: 0;
32
+ }
33
+
34
+ :root {
35
+ --wf-ink: #2b2b2b; /* 主要テキスト */
36
+ --wf-muted: #777; /* 補助テキスト・プレースホルダ */
37
+ --wf-line: #c9c9c9; /* 枠線 */
38
+ --wf-fill: #f2f2f2; /* 面(薄) */
39
+ --wf-fill-2: #e4e4e4; /* 面(中) */
40
+ --wf-fill-3: #d2d2d2; /* 面(濃)/ primary ボタン */
41
+ --wf-bg: #ffffff;
42
+ --wf-radius: 4px;
43
+ --wf-gap: 12px;
44
+ --wf-pad: 16px;
45
+ }
46
+
47
+ body {
48
+ font-family: -apple-system, "Segoe UI", "Noto Sans JP", "Hiragino Sans", sans-serif;
49
+ color: var(--wf-ink);
50
+ background: #eaeaea;
51
+ line-height: 1.5;
52
+ font-size: 14px;
53
+ }
54
+
55
+ /* ===== ラベル(画面名・状態名の注記) ===== */
56
+ .wf-screen-label {
57
+ max-width: 1100px;
58
+ margin: 16px auto 0;
59
+ padding: 0 16px;
60
+ font-size: 12px;
61
+ color: var(--wf-muted);
62
+ letter-spacing: 0.04em;
63
+ }
64
+ .wf-screen-label strong {
65
+ color: var(--wf-ink);
66
+ font-size: 13px;
67
+ }
68
+
69
+ /* ===== Page shell ===== */
70
+ .wf-page {
71
+ max-width: 1100px;
72
+ margin: 8px auto 32px;
73
+ background: var(--wf-bg);
74
+ border: 1px solid var(--wf-line);
75
+ border-radius: var(--wf-radius);
76
+ overflow: hidden;
77
+ }
78
+ /* モバイル枠(幅 390px 固定)でプレビューしたい場合に付与 */
79
+ .wf-page--mobile {
80
+ max-width: 390px;
81
+ }
82
+
83
+ /* ===== Header(グローバルヘッダー) ===== */
84
+ .wf-header {
85
+ display: flex;
86
+ align-items: center;
87
+ gap: var(--wf-gap);
88
+ padding: 12px var(--wf-pad);
89
+ border-bottom: 1px solid var(--wf-line);
90
+ background: var(--wf-fill);
91
+ }
92
+ .wf-header__logo {
93
+ font-weight: 700;
94
+ padding: 6px 10px;
95
+ border: 1px solid var(--wf-line);
96
+ border-radius: var(--wf-radius);
97
+ background: var(--wf-bg);
98
+ }
99
+ .wf-header__nav {
100
+ display: flex;
101
+ gap: 16px;
102
+ flex-wrap: wrap;
103
+ color: var(--wf-muted);
104
+ }
105
+ .wf-header__spacer { flex: 1; }
106
+
107
+ /* ===== Body layout(サイドバー + メイン) ===== */
108
+ .wf-body {
109
+ display: flex;
110
+ min-height: 360px;
111
+ }
112
+ .wf-sidebar {
113
+ width: 200px;
114
+ flex-shrink: 0;
115
+ border-right: 1px solid var(--wf-line);
116
+ background: var(--wf-fill);
117
+ padding: var(--wf-pad);
118
+ }
119
+ .wf-sidebar__item {
120
+ padding: 8px 10px;
121
+ border-radius: var(--wf-radius);
122
+ color: var(--wf-muted);
123
+ }
124
+ .wf-sidebar__item--active {
125
+ background: var(--wf-fill-2);
126
+ color: var(--wf-ink);
127
+ font-weight: 600;
128
+ }
129
+ .wf-main {
130
+ flex: 1;
131
+ padding: var(--wf-pad);
132
+ min-width: 0;
133
+ }
134
+
135
+ /* モバイル: サイドバーは隠してハンバーガー前提(注記用ダミー) */
136
+ @media (max-width: 767px) {
137
+ .wf-sidebar { display: none; }
138
+ }
139
+
140
+ /* ===== 見出し / パンくず / タブ ===== */
141
+ .wf-breadcrumb {
142
+ color: var(--wf-muted);
143
+ font-size: 12px;
144
+ margin-bottom: 8px;
145
+ }
146
+ .wf-title {
147
+ font-size: 20px;
148
+ font-weight: 700;
149
+ margin-bottom: 4px;
150
+ }
151
+ .wf-subtitle {
152
+ color: var(--wf-muted);
153
+ margin-bottom: var(--wf-pad);
154
+ }
155
+ .wf-tabs {
156
+ display: flex;
157
+ gap: 4px;
158
+ border-bottom: 1px solid var(--wf-line);
159
+ margin-bottom: var(--wf-pad);
160
+ }
161
+ .wf-tabs__item {
162
+ padding: 8px 14px;
163
+ color: var(--wf-muted);
164
+ border: 1px solid transparent;
165
+ border-bottom: none;
166
+ }
167
+ .wf-tabs__item--active {
168
+ color: var(--wf-ink);
169
+ font-weight: 600;
170
+ border-color: var(--wf-line);
171
+ border-radius: var(--wf-radius) var(--wf-radius) 0 0;
172
+ background: var(--wf-fill);
173
+ margin-bottom: -1px;
174
+ }
175
+
176
+ /* ===== ツールバー(件数 + アクション) ===== */
177
+ .wf-toolbar {
178
+ display: flex;
179
+ align-items: center;
180
+ gap: var(--wf-gap);
181
+ flex-wrap: wrap;
182
+ margin-bottom: var(--wf-pad);
183
+ }
184
+ .wf-toolbar__spacer { flex: 1; }
185
+ .wf-count { color: var(--wf-muted); }
186
+
187
+ /* ===== 検索 / フィルタ ===== */
188
+ .wf-search {
189
+ border: 1px solid var(--wf-line);
190
+ border-radius: var(--wf-radius);
191
+ margin-bottom: var(--wf-pad);
192
+ overflow: hidden;
193
+ }
194
+ .wf-search__head {
195
+ padding: 8px var(--wf-pad);
196
+ background: var(--wf-fill-2);
197
+ font-weight: 600;
198
+ }
199
+ .wf-search__body {
200
+ padding: var(--wf-pad);
201
+ display: grid;
202
+ grid-template-columns: 1fr;
203
+ gap: var(--wf-gap);
204
+ }
205
+ @media (min-width: 768px) {
206
+ .wf-search__body { grid-template-columns: 1fr 1fr; }
207
+ }
208
+ .wf-search__actions {
209
+ grid-column: 1 / -1;
210
+ display: flex;
211
+ justify-content: flex-end;
212
+ gap: 8px;
213
+ }
214
+
215
+ /* ===== Form / Field ===== */
216
+ .wf-form {
217
+ display: grid;
218
+ grid-template-columns: 1fr;
219
+ gap: var(--wf-gap);
220
+ }
221
+ @media (min-width: 768px) {
222
+ .wf-form--2col { grid-template-columns: 1fr 1fr; }
223
+ }
224
+ .wf-field { display: flex; flex-direction: column; gap: 4px; }
225
+ .wf-field--full { grid-column: 1 / -1; }
226
+ .wf-label { font-size: 12px; color: var(--wf-ink); font-weight: 600; }
227
+ .wf-label--required::after { content: " *"; color: var(--wf-muted); }
228
+ .wf-input,
229
+ .wf-select,
230
+ .wf-textarea {
231
+ border: 1px solid var(--wf-line);
232
+ border-radius: var(--wf-radius);
233
+ background: var(--wf-bg);
234
+ padding: 8px 10px;
235
+ color: var(--wf-muted);
236
+ min-height: 36px;
237
+ }
238
+ .wf-textarea { min-height: 88px; }
239
+ /* セレクトのプルダウン矢印は HTML 側に「▾」を明示的に書く(例: <span class="wf-select">すべて ▾</span>) */
240
+ .wf-help { font-size: 11px; color: var(--wf-muted); }
241
+ .wf-error { font-size: 11px; color: var(--wf-ink); font-weight: 600; }
242
+
243
+ /* ===== Buttons ===== */
244
+ .wf-button {
245
+ display: inline-flex;
246
+ align-items: center;
247
+ justify-content: center;
248
+ gap: 6px;
249
+ min-height: 36px;
250
+ padding: 8px 16px;
251
+ border: 1px solid var(--wf-line);
252
+ border-radius: var(--wf-radius);
253
+ background: var(--wf-bg);
254
+ color: var(--wf-ink);
255
+ font: inherit;
256
+ cursor: default;
257
+ }
258
+ .wf-button--primary { background: var(--wf-fill-3); font-weight: 600; }
259
+ .wf-button--ghost { border-color: transparent; color: var(--wf-muted); }
260
+ .wf-button--sm { min-height: 28px; padding: 4px 10px; font-size: 12px; }
261
+
262
+ /* ===== Table ===== */
263
+ .wf-table-wrap {
264
+ border: 1px solid var(--wf-line);
265
+ border-radius: var(--wf-radius);
266
+ overflow-x: auto;
267
+ }
268
+ .wf-table {
269
+ width: 100%;
270
+ border-collapse: collapse;
271
+ min-width: 640px;
272
+ }
273
+ .wf-table th,
274
+ .wf-table td {
275
+ text-align: left;
276
+ padding: 10px 12px;
277
+ border-bottom: 1px solid var(--wf-line);
278
+ white-space: nowrap;
279
+ }
280
+ .wf-table thead th {
281
+ background: var(--wf-fill-2);
282
+ font-weight: 600;
283
+ }
284
+ .wf-table tbody tr:last-child td { border-bottom: none; }
285
+ .wf-table td.wf-td--muted { color: var(--wf-muted); }
286
+
287
+ /* ===== Cards / Grid ===== */
288
+ .wf-grid {
289
+ display: grid;
290
+ grid-template-columns: 1fr;
291
+ gap: var(--wf-gap);
292
+ }
293
+ @media (min-width: 768px) { .wf-grid--2 { grid-template-columns: repeat(2, 1fr); } }
294
+ @media (min-width: 1024px) { .wf-grid--3 { grid-template-columns: repeat(3, 1fr); } }
295
+ .wf-card {
296
+ border: 1px solid var(--wf-line);
297
+ border-radius: var(--wf-radius);
298
+ padding: var(--wf-pad);
299
+ background: var(--wf-bg);
300
+ display: flex;
301
+ flex-direction: column;
302
+ gap: 6px;
303
+ }
304
+ .wf-card__title { font-weight: 600; }
305
+ .wf-card__meta { color: var(--wf-muted); font-size: 12px; }
306
+
307
+ /* ===== Kanban ===== */
308
+ .wf-kanban {
309
+ display: grid;
310
+ grid-template-columns: 1fr;
311
+ gap: var(--wf-gap);
312
+ }
313
+ @media (min-width: 768px) {
314
+ .wf-kanban--3 { grid-template-columns: repeat(3, 1fr); }
315
+ }
316
+ .wf-kanban__col {
317
+ background: var(--wf-fill);
318
+ border: 1px solid var(--wf-line);
319
+ border-radius: var(--wf-radius);
320
+ padding: 10px;
321
+ display: flex;
322
+ flex-direction: column;
323
+ gap: 10px;
324
+ }
325
+ .wf-kanban__head { font-weight: 600; }
326
+
327
+ /* ===== Tag / Badge ===== */
328
+ .wf-tag {
329
+ display: inline-block;
330
+ padding: 2px 8px;
331
+ border: 1px solid var(--wf-line);
332
+ border-radius: 999px;
333
+ font-size: 11px;
334
+ color: var(--wf-muted);
335
+ background: var(--wf-fill);
336
+ }
337
+
338
+ /* ===== Placeholder(画像 / アバター) ===== */
339
+ .wf-img {
340
+ position: relative;
341
+ background: var(--wf-fill);
342
+ border: 1px solid var(--wf-line);
343
+ border-radius: var(--wf-radius);
344
+ min-height: 96px;
345
+ }
346
+ .wf-img::after {
347
+ content: "";
348
+ position: absolute;
349
+ inset: 0;
350
+ background:
351
+ linear-gradient(to top right, transparent calc(50% - 1px), var(--wf-line), transparent calc(50% + 1px)),
352
+ linear-gradient(to top left, transparent calc(50% - 1px), var(--wf-line), transparent calc(50% + 1px));
353
+ }
354
+ .wf-avatar {
355
+ width: 40px;
356
+ height: 40px;
357
+ border-radius: 999px;
358
+ background: var(--wf-fill-2);
359
+ border: 1px solid var(--wf-line);
360
+ flex-shrink: 0;
361
+ }
362
+
363
+ /* ===== Pagination ===== */
364
+ .wf-pagination {
365
+ display: flex;
366
+ justify-content: center;
367
+ gap: 4px;
368
+ margin-top: var(--wf-pad);
369
+ }
370
+ .wf-pagination__item {
371
+ min-width: 32px;
372
+ min-height: 32px;
373
+ display: inline-flex;
374
+ align-items: center;
375
+ justify-content: center;
376
+ border: 1px solid var(--wf-line);
377
+ border-radius: var(--wf-radius);
378
+ color: var(--wf-muted);
379
+ }
380
+ .wf-pagination__item--active {
381
+ background: var(--wf-fill-2);
382
+ color: var(--wf-ink);
383
+ font-weight: 600;
384
+ }
385
+
386
+ /* ===== 空状態 / エラー状態 ===== */
387
+ .wf-empty {
388
+ border: 1px dashed var(--wf-line);
389
+ border-radius: var(--wf-radius);
390
+ padding: 40px var(--wf-pad);
391
+ text-align: center;
392
+ color: var(--wf-muted);
393
+ }
394
+
395
+ /* ===== Modal / Dialog(重ね表示はせず、注記付きで並置) ===== */
396
+ .wf-modal {
397
+ max-width: 480px;
398
+ margin: 0 auto;
399
+ border: 1px solid var(--wf-line);
400
+ border-radius: var(--wf-radius);
401
+ background: var(--wf-bg);
402
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
403
+ }
404
+ .wf-modal__head {
405
+ padding: 12px var(--wf-pad);
406
+ border-bottom: 1px solid var(--wf-line);
407
+ font-weight: 600;
408
+ display: flex;
409
+ align-items: center;
410
+ }
411
+ .wf-modal__head .wf-toolbar__spacer { flex: 1; }
412
+ .wf-modal__body { padding: var(--wf-pad); display: grid; gap: var(--wf-gap); }
413
+ .wf-modal__foot {
414
+ padding: 12px var(--wf-pad);
415
+ border-top: 1px solid var(--wf-line);
416
+ display: flex;
417
+ justify-content: flex-end;
418
+ gap: 8px;
419
+ }
420
+
421
+ /* ===== 注記(インタラクション説明など) ===== */
422
+ .wf-note {
423
+ font-size: 11px;
424
+ color: var(--wf-muted);
425
+ border-left: 3px solid var(--wf-line);
426
+ padding: 2px 8px;
427
+ margin-top: 6px;
428
+ }
429
+
430
+ /* ===== ユーティリティ ===== */
431
+ .wf-row { display: flex; align-items: center; gap: var(--wf-gap); flex-wrap: wrap; }
432
+ .wf-stack { display: flex; flex-direction: column; gap: 8px; }
433
+ .wf-mt { margin-top: var(--wf-pad); }
434
+ .wf-muted { color: var(--wf-muted); }
435
+ </style>
436
+ </head>
437
+ <body>
438
+ <p class="wf-screen-label"><strong>一覧画面(toC)</strong> / 状態: 通常</p>
439
+
440
+ <div class="wf-page">
441
+ <header class="wf-header">
442
+ <span class="wf-header__logo">Sample Service</span>
443
+ <nav class="wf-header__nav">
444
+ <span>ホーム</span>
445
+ <span>一覧</span>
446
+ <span>お気に入り</span>
447
+ </nav>
448
+ <span class="wf-header__spacer"></span>
449
+ <span class="wf-button wf-button--sm">アカウント</span>
450
+ </header>
451
+
452
+ <div class="wf-body">
453
+ <main class="wf-main">
454
+ <h1 class="wf-title">一覧</h1>
455
+ <p class="wf-subtitle">条件で絞り込んで、気になるものを保存できます。</p>
456
+
457
+ <section class="wf-search">
458
+ <div class="wf-search__head">絞り込み</div>
459
+ <div class="wf-search__body">
460
+ <div class="wf-field">
461
+ <span class="wf-label">キーワード</span>
462
+ <span class="wf-input">キーワードを入力</span>
463
+ </div>
464
+ <div class="wf-field">
465
+ <span class="wf-label">カテゴリ</span>
466
+ <span class="wf-select">すべて ▾</span>
467
+ </div>
468
+ <div class="wf-field">
469
+ <span class="wf-label">エリア</span>
470
+ <span class="wf-select">指定なし ▾</span>
471
+ </div>
472
+ <div class="wf-field">
473
+ <span class="wf-label">並び替え</span>
474
+ <span class="wf-select">新着順 ▾</span>
475
+ </div>
476
+ <div class="wf-search__actions">
477
+ <span class="wf-button">リセット</span>
478
+ <span class="wf-button wf-button--primary">検索</span>
479
+ </div>
480
+ </div>
481
+ </section>
482
+
483
+ <div class="wf-toolbar">
484
+ <span class="wf-count">該当 128 件</span>
485
+ </div>
486
+
487
+ <div class="wf-grid wf-grid--2 wf-grid--3">
488
+ <article class="wf-card">
489
+ <div class="wf-img"></div>
490
+ <div class="wf-card__title">アイテムのタイトル</div>
491
+ <div class="wf-card__meta">カテゴリ ・ エリア ・ 3 日前</div>
492
+ <div class="wf-row">
493
+ <span class="wf-tag">タグA</span>
494
+ <span class="wf-tag">タグB</span>
495
+ </div>
496
+ <div class="wf-row wf-mt">
497
+ <span class="wf-button wf-button--sm">保存</span>
498
+ <span class="wf-button wf-button--sm wf-button--primary">詳細を見る</span>
499
+ </div>
500
+ </article>
501
+ <article class="wf-card">
502
+ <div class="wf-img"></div>
503
+ <div class="wf-card__title">アイテムのタイトル</div>
504
+ <div class="wf-card__meta">カテゴリ ・ エリア ・ 5 日前</div>
505
+ <div class="wf-row">
506
+ <span class="wf-tag">タグA</span>
507
+ </div>
508
+ <div class="wf-row wf-mt">
509
+ <span class="wf-button wf-button--sm">保存</span>
510
+ <span class="wf-button wf-button--sm wf-button--primary">詳細を見る</span>
511
+ </div>
512
+ </article>
513
+ <article class="wf-card">
514
+ <div class="wf-img"></div>
515
+ <div class="wf-card__title">アイテムのタイトル</div>
516
+ <div class="wf-card__meta">カテゴリ ・ エリア ・ 1 週間前</div>
517
+ <div class="wf-row">
518
+ <span class="wf-tag">タグC</span>
519
+ </div>
520
+ <div class="wf-row wf-mt">
521
+ <span class="wf-button wf-button--sm">保存</span>
522
+ <span class="wf-button wf-button--sm wf-button--primary">詳細を見る</span>
523
+ </div>
524
+ </article>
525
+ </div>
526
+
527
+ <nav class="wf-pagination">
528
+ <span class="wf-pagination__item">前へ</span>
529
+ <span class="wf-pagination__item wf-pagination__item--active">1</span>
530
+ <span class="wf-pagination__item">2</span>
531
+ <span class="wf-pagination__item">3</span>
532
+ <span class="wf-pagination__item">次へ</span>
533
+ </nav>
534
+ </main>
535
+ </div>
536
+ </div>
537
+ </body>
538
+ </html>
@@ -0,0 +1,53 @@
1
+ # ジャーニー → 画面の起こし方
2
+
3
+ REQUIREMENTS.md のユーザージャーニーから WF にすべき画面を導くための手順。
4
+
5
+ ## 1. ジャーニーのステップを「画面」に割り当てる
6
+
7
+ 各ジャーニーの手順を読み、**ユーザーが何かを見る / 操作する単位**で画面を切る。
8
+
9
+ 例(一覧 → 詳細 → 申込のジャーニー):
10
+
11
+ | ジャーニー手順 | 画面 |
12
+ | -------------- | ---- |
13
+ | 一覧を検索・絞り込みする | 一覧画面(検索条件 + 結果テーブル/カード) |
14
+ | 1 件を選んで詳細を見る | 詳細画面 |
15
+ | 申込フォームを入力して送信する | 申込フォーム(モーダル or 専用画面) |
16
+ | 送信完了を確認する | 完了画面 / トースト |
17
+
18
+ - 1 ジャーニーが複数画面にまたがる、複数ジャーニーが 1 画面を共有する、どちらもある。
19
+ - 重複を避けるため、**先に全ジャーニーを通して画面の集合を作ってから** WF 化する。
20
+
21
+ ## 2. 各画面の「状態」を決める
22
+
23
+ P0 / P1 で「期待結果」や「エラーケース」に出てくる状態を WF にする。
24
+
25
+ | 状態 | 作るべきか | クラス例 |
26
+ | ---- | ---------- | -------- |
27
+ | 通常(データあり) | 必須 | `wf-table` / `wf-grid` / `wf-card` |
28
+ | 空(0 件 / 未登録) | 一覧・ダッシュボードでは必須 | `wf-empty` |
29
+ | エラー(入力不正・取得失敗) | フォーム・主要操作では必須 | `wf-error` / `wf-empty`(取得失敗メッセージ) |
30
+ | ローディング | 任意(必要なら注記で代替) | `wf-note` で「読込中スケルトン」と明記 |
31
+
32
+ 状態違いは別ファイルにする(例: `list.html`, `list-empty.html`)か、1 画面内に注記(`wf-note`)で併記する。
33
+
34
+ ## 3. レイアウトの型を選ぶ
35
+
36
+ | 画面タイプ | 骨格 |
37
+ | ---------- | ---- |
38
+ | toC 一覧(検索 + カード) | `wf-header` → `wf-main`(`wf-search` + `wf-grid` + `wf-pagination`) |
39
+ | toB 管理一覧(検索 + テーブル) | `wf-header` → `wf-body`(`wf-sidebar` + `wf-main`: `wf-search` + `wf-toolbar` + `wf-table` + `wf-pagination`) |
40
+ | フォーム / 詳細編集 | `wf-form(--2col)` + `wf-field` + フッターに `wf-button--primary` |
41
+ | ステータス管理(カンバン) | `wf-kanban--3` + `wf-kanban__col` + `wf-card` |
42
+ | 確認 / 申込ダイアログ | `wf-modal`(`wf-modal__head/body/foot`) |
43
+
44
+ ## 4. 文言は SCREEN_ITEMS_DEFINITION.md / REQUIREMENTS.md から取る
45
+
46
+ - フォーム項目名・必須/任意・選択肢は `SCREEN_ITEMS_DEFINITION.md` があればそれが出所(なければ REQUIREMENTS.md の表示要素から)。
47
+ - ボタン文言・タブ名・空状態メッセージは REQUIREMENTS.md のジャーニー / 期待結果から拾う。
48
+ - **想像で増やさない**。Spec にない項目・ボタンを WF に足すと、WF が Spec を上書きしてしまい SSOT が壊れる。足したくなったら先に REQUIREMENTS.md を更新する。
49
+
50
+ ## 5. index と REQUIREMENTS のリンクを最後に整える
51
+
52
+ - `index.html` に全画面・全状態を列挙。
53
+ - REQUIREMENTS.md「3. UI/UX デザイン」から `./wireframes/index.html` を指し、各画面の要点(タイトル・主要ボタン・表示要素)をテキストでも残す(HTML を開けない読者・差分レビュー用)。