@profpowell/vb-project-planning 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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/vb-project-planning.css +1603 -0
  4. package/dist/vb-project-planning.js +11138 -0
  5. package/dist/vb-project-planning.min.css +1 -0
  6. package/dist/vb-project-planning.min.js +3312 -0
  7. package/package.json +80 -0
  8. package/src/index.css +14 -0
  9. package/src/index.js +26 -0
  10. package/src/lib/bundle-registry.js +156 -0
  11. package/src/lib/diff-by-key.js +86 -0
  12. package/src/lib/portrait-url.js +87 -0
  13. package/src/lib/vb-collection.js +122 -0
  14. package/src/lib/vb-element.js +96 -0
  15. package/src/lib/vb-store.js +200 -0
  16. package/src/lib/vb-view-transition.js +44 -0
  17. package/src/utils/copy-init.js +287 -0
  18. package/src/web-components/_ux-base.js +106 -0
  19. package/src/web-components/adr-wc/README.md +77 -0
  20. package/src/web-components/adr-wc/api.json +26 -0
  21. package/src/web-components/adr-wc/logic.js +376 -0
  22. package/src/web-components/adr-wc/static.html +17 -0
  23. package/src/web-components/adr-wc/styles.js +338 -0
  24. package/src/web-components/burndown-chart/api.json +74 -0
  25. package/src/web-components/burndown-chart/logic.js +198 -0
  26. package/src/web-components/burndown-chart/static.html +31 -0
  27. package/src/web-components/burndown-chart/styles.css +59 -0
  28. package/src/web-components/capacity-plan/_capacity-utils.js +56 -0
  29. package/src/web-components/capacity-plan/api.json +20 -0
  30. package/src/web-components/capacity-plan/logic.js +222 -0
  31. package/src/web-components/capacity-plan/static.html +24 -0
  32. package/src/web-components/capacity-plan/styles.css +84 -0
  33. package/src/web-components/empathy-map/api.json +31 -0
  34. package/src/web-components/empathy-map/logic.js +502 -0
  35. package/src/web-components/empathy-map/static.html +32 -0
  36. package/src/web-components/empathy-map/styles.js +534 -0
  37. package/src/web-components/gantt-chart/README.md +91 -0
  38. package/src/web-components/gantt-chart/api.json +20 -0
  39. package/src/web-components/gantt-chart/logic.js +812 -0
  40. package/src/web-components/gantt-chart/static.html +60 -0
  41. package/src/web-components/gantt-chart/styles.css +391 -0
  42. package/src/web-components/impact-effort/api.json +21 -0
  43. package/src/web-components/impact-effort/logic.js +392 -0
  44. package/src/web-components/impact-effort/static.html +23 -0
  45. package/src/web-components/impact-effort/styles.css +193 -0
  46. package/src/web-components/iron-triangle/_capacity.js +83 -0
  47. package/src/web-components/iron-triangle/_triangle-geometry.js +322 -0
  48. package/src/web-components/iron-triangle/api.json +26 -0
  49. package/src/web-components/iron-triangle/logic.js +474 -0
  50. package/src/web-components/iron-triangle/static.html +28 -0
  51. package/src/web-components/iron-triangle/styles.css +158 -0
  52. package/src/web-components/kanban-board/api.json +24 -0
  53. package/src/web-components/kanban-board/logic.js +698 -0
  54. package/src/web-components/kanban-board/static.html +20 -0
  55. package/src/web-components/kanban-board/styles.css +242 -0
  56. package/src/web-components/product-roadmap/api.json +118 -0
  57. package/src/web-components/product-roadmap/logic.js +460 -0
  58. package/src/web-components/product-roadmap/static.html +44 -0
  59. package/src/web-components/product-roadmap/styles.css +158 -0
  60. package/src/web-components/quadrant-grid/api.json +125 -0
  61. package/src/web-components/quadrant-grid/logic.js +397 -0
  62. package/src/web-components/quadrant-grid/static.html +49 -0
  63. package/src/web-components/quadrant-grid/styles.css +184 -0
  64. package/src/web-components/quality-target/_quality-utils.js +460 -0
  65. package/src/web-components/quality-target/api.json +30 -0
  66. package/src/web-components/quality-target/logic.js +516 -0
  67. package/src/web-components/quality-target/static.html +22 -0
  68. package/src/web-components/quality-target/styles.css +203 -0
  69. package/src/web-components/requirement-card/api.json +25 -0
  70. package/src/web-components/requirement-card/logic.js +166 -0
  71. package/src/web-components/requirement-card/static.html +36 -0
  72. package/src/web-components/requirement-card/styles.js +114 -0
  73. package/src/web-components/review-surface/README.md +178 -0
  74. package/src/web-components/review-surface/api.json +30 -0
  75. package/src/web-components/review-surface/logic.js +807 -0
  76. package/src/web-components/review-surface/static.html +33 -0
  77. package/src/web-components/review-surface/styles.js +459 -0
  78. package/src/web-components/risk-register/api.json +47 -0
  79. package/src/web-components/risk-register/logic.js +180 -0
  80. package/src/web-components/risk-register/static.html +46 -0
  81. package/src/web-components/risk-register/styles.css +37 -0
  82. package/src/web-components/story-map/api.json +22 -0
  83. package/src/web-components/story-map/logic.js +445 -0
  84. package/src/web-components/story-map/static.html +35 -0
  85. package/src/web-components/story-map/styles.css +169 -0
  86. package/src/web-components/traceability-matrix/api.json +84 -0
  87. package/src/web-components/traceability-matrix/logic.js +243 -0
  88. package/src/web-components/traceability-matrix/static.html +41 -0
  89. package/src/web-components/traceability-matrix/styles.css +94 -0
  90. package/src/web-components/user-journey/api.json +84 -0
  91. package/src/web-components/user-journey/logic.js +368 -0
  92. package/src/web-components/user-journey/static.html +14 -0
  93. package/src/web-components/user-journey/styles.js +317 -0
  94. package/src/web-components/user-persona/api.json +35 -0
  95. package/src/web-components/user-persona/logic.js +502 -0
  96. package/src/web-components/user-persona/static.html +20 -0
  97. package/src/web-components/user-persona/styles.js +299 -0
  98. package/src/web-components/user-story/api.json +35 -0
  99. package/src/web-components/user-story/logic.js +567 -0
  100. package/src/web-components/user-story/static.html +27 -0
  101. package/src/web-components/user-story/styles.js +332 -0
  102. package/src/web-components/work-item/README.md +85 -0
  103. package/src/web-components/work-item/api.json +30 -0
  104. package/src/web-components/work-item/logic.js +414 -0
  105. package/src/web-components/work-item/static.html +24 -0
  106. package/src/web-components/work-item/styles.js +376 -0
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Shadow DOM styles for user-story component
3
+ *
4
+ * 3-tier token pattern:
5
+ * var(--user-story-*, var(--color-*, fallback))
6
+ */
7
+ const styles = `
8
+ :host {
9
+ --_bg: var(--user-story-bg, var(--color-surface, #ffffff));
10
+ --_text: var(--user-story-text, var(--color-text, #1a1a1a));
11
+ --_muted: var(--user-story-muted, var(--color-text-muted, #666));
12
+ --_border: var(--user-story-border, var(--color-border, #e0e0e0));
13
+ --_accent: var(--user-story-accent, var(--color-interactive, #0066cc));
14
+ --_card-bg: var(--user-story-card-bg, var(--color-surface-raised, #f8f9fa));
15
+ --_highlight: var(--user-story-highlight, color-mix(in srgb, var(--_accent) 8%, transparent));
16
+ --_radius: var(--user-story-radius, var(--radius-l, 0.75rem));
17
+ --_shadow: var(--user-story-shadow, var(--shadow-sm));
18
+ --_shadow-hover: var(--user-story-shadow-hover, var(--shadow-md));
19
+ --_duration: var(--user-story-duration, var(--duration-normal, 200ms));
20
+ --_ease: var(--user-story-ease, var(--ease-default, ease));
21
+ --_space-xs: var(--user-story-space-xs, var(--size-xs, 0.5rem));
22
+ --_space-s: var(--user-story-space-s, var(--size-s, 0.75rem));
23
+ --_space-m: var(--user-story-space-m, var(--size-m, 1rem));
24
+ --_font-xs: var(--user-story-font-xs, var(--font-size-xs, 0.75rem));
25
+ --_font-sm: var(--user-story-font-sm, var(--font-size-sm, 0.875rem));
26
+ --_font-md: var(--user-story-font-md, var(--font-size-md, 1rem));
27
+ --_font-lg: var(--user-story-font-lg, var(--font-size-lg, 1.125rem));
28
+ --_font-mono: var(--user-story-font-mono, var(--font-mono, ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace));
29
+ --_radius-s: var(--user-story-radius-s, var(--radius-s, 0.25rem));
30
+ --_radius-full: var(--user-story-radius-full, var(--radius-full, 9999px));
31
+
32
+ display: block;
33
+ font-family: var(--user-story-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
34
+ }
35
+
36
+ .story-card {
37
+ background: var(--_bg);
38
+ border: 1px solid var(--_border);
39
+ border-radius: var(--_radius);
40
+ overflow: hidden;
41
+ box-shadow: var(--_shadow);
42
+ transition: box-shadow var(--_duration) var(--_ease), transform var(--_duration) var(--_ease);
43
+ }
44
+
45
+ .story-card:hover {
46
+ box-shadow: var(--_shadow-hover);
47
+ }
48
+
49
+ .story-header {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: space-between;
53
+ padding: var(--_space-s) var(--_space-m);
54
+ background: var(--_card-bg);
55
+ border-bottom: 1px solid var(--_border);
56
+ gap: var(--_space-s);
57
+ flex-wrap: wrap;
58
+ }
59
+
60
+ .story-meta {
61
+ display: flex;
62
+ align-items: center;
63
+ gap: var(--_space-xs);
64
+ flex-wrap: wrap;
65
+ }
66
+
67
+ .story-id {
68
+ font-size: var(--_font-xs);
69
+ font-weight: 600;
70
+ color: var(--_muted);
71
+ font-family: var(--_font-mono);
72
+ }
73
+
74
+ .epic-badge {
75
+ font-size: 11px;
76
+ padding: 3px 8px;
77
+ border-radius: var(--_radius-s);
78
+ background: var(--_highlight);
79
+ color: var(--_accent);
80
+ font-weight: 500;
81
+ }
82
+
83
+ .story-badges {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: var(--_space-xs);
87
+ }
88
+
89
+ .priority-badge,
90
+ .status-badge {
91
+ font-size: 11px;
92
+ padding: 4px 10px;
93
+ border-radius: var(--_radius-full);
94
+ font-weight: 600;
95
+ text-transform: uppercase;
96
+ letter-spacing: 0.3px;
97
+ }
98
+
99
+ .points-badge {
100
+ width: 28px;
101
+ height: 28px;
102
+ border-radius: var(--_radius-full);
103
+ background: var(--_accent);
104
+ color: white;
105
+ font-size: var(--_font-xs);
106
+ font-weight: 700;
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ }
111
+
112
+ .story-body {
113
+ padding: 20px;
114
+ }
115
+
116
+ :host([compact]) .story-body {
117
+ padding: var(--_space-m);
118
+ }
119
+
120
+ .story-statement {
121
+ font-size: var(--_font-lg);
122
+ line-height: 1.6;
123
+ color: var(--_text);
124
+ margin: 0;
125
+ }
126
+
127
+ :host([compact]) .story-statement {
128
+ font-size: 15px;
129
+ }
130
+
131
+ .keyword {
132
+ font-weight: 600;
133
+ color: var(--_accent);
134
+ }
135
+
136
+ .persona-text {
137
+ background: var(--_highlight);
138
+ padding: 2px 6px;
139
+ border-radius: var(--_radius-s);
140
+ font-weight: 500;
141
+ }
142
+
143
+ .persona-text--link {
144
+ display: inline-flex;
145
+ align-items: center;
146
+ gap: 3px;
147
+ color: var(--_accent);
148
+ text-decoration: none;
149
+ }
150
+
151
+ .persona-text--link svg {
152
+ width: 13px;
153
+ height: 13px;
154
+ flex-shrink: 0;
155
+ }
156
+
157
+ .persona-text--link:hover {
158
+ text-decoration: underline;
159
+ }
160
+
161
+ .action-text {
162
+ font-weight: 500;
163
+ }
164
+
165
+ .benefit-text {
166
+ font-style: italic;
167
+ color: var(--_muted);
168
+ }
169
+
170
+ .story-sections {
171
+ border-top: 1px solid var(--_border);
172
+ }
173
+
174
+ .section {
175
+ padding: 16px 20px;
176
+ border-bottom: 1px solid var(--_border);
177
+ }
178
+
179
+ .section:last-child {
180
+ border-bottom: none;
181
+ }
182
+
183
+ .section-header {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: var(--_space-xs);
187
+ margin-bottom: var(--_space-s);
188
+ }
189
+
190
+ .section-icon {
191
+ width: 24px;
192
+ height: 24px;
193
+ border-radius: 6px;
194
+ display: flex;
195
+ align-items: center;
196
+ justify-content: center;
197
+ background: var(--_accent);
198
+ }
199
+
200
+ .section-icon svg {
201
+ width: 14px;
202
+ height: 14px;
203
+ fill: white;
204
+ }
205
+
206
+ /* Semantic section-icon colors — driven by VB theme tokens so they shift
207
+ with the active theme rather than fighting it. */
208
+ .section-icon.acceptance { background: var(--color-success, #22c55e); }
209
+ .section-icon.notes { background: var(--color-warning, #f59e0b); }
210
+ .section-icon.tasks { background: var(--color-accent, #8b5cf6); }
211
+
212
+ .section-title {
213
+ font-size: var(--_font-xs);
214
+ font-weight: 600;
215
+ color: var(--_muted);
216
+ text-transform: uppercase;
217
+ letter-spacing: 0.5px;
218
+ }
219
+
220
+ .section-content {
221
+ color: var(--_text);
222
+ font-size: var(--_font-sm);
223
+ line-height: 1.6;
224
+ }
225
+
226
+ /* Slotted content styling */
227
+ .section-content ::slotted(ul),
228
+ .section-content ::slotted(ol) {
229
+ margin: 0;
230
+ padding-left: 20px;
231
+ }
232
+
233
+ .section-content ::slotted(li) {
234
+ margin-bottom: 6px;
235
+ }
236
+
237
+ .section-content ::slotted(p) {
238
+ margin: 0;
239
+ }
240
+
241
+ /* Empty-slot fallback */
242
+ .slot-fallback {
243
+ color: var(--_muted);
244
+ font-style: italic;
245
+ }
246
+
247
+ @media (max-width: 480px) {
248
+ .story-header {
249
+ flex-direction: column;
250
+ align-items: flex-start;
251
+ }
252
+
253
+ .story-badges {
254
+ width: 100%;
255
+ justify-content: flex-start;
256
+ }
257
+ }
258
+
259
+ @media (prefers-reduced-motion: reduce) {
260
+ .story-card {
261
+ transition: none;
262
+ }
263
+ }
264
+
265
+ /* ── Slotted title (minimal mode heading) ──────────── */
266
+ .story-title-wrap {
267
+ margin: 0;
268
+ }
269
+
270
+ ::slotted([slot="title"]) {
271
+ font-size: var(--_font-sm) !important;
272
+ font-weight: 600 !important;
273
+ color: var(--_text) !important;
274
+ margin: 0 !important;
275
+ }
276
+
277
+ .story-title-fallback {
278
+ font-size: var(--_font-sm);
279
+ font-weight: 600;
280
+ color: var(--_text);
281
+ }
282
+
283
+ /* Minimal detail level */
284
+ :host([detail="minimal"]) .story-card {
285
+ padding: var(--_space-xs);
286
+ }
287
+
288
+ :host([detail="minimal"]) .story-header {
289
+ display: none;
290
+ }
291
+
292
+ :host([detail="minimal"]) .story-sections {
293
+ display: none;
294
+ }
295
+
296
+ :host([detail="minimal"]) .story-body {
297
+ padding: var(--_space-xs) var(--_space-s);
298
+ }
299
+
300
+ :host([detail="minimal"]) .story-card {
301
+ cursor: pointer;
302
+ }
303
+
304
+ :host([detail="minimal"]) .story-card:hover {
305
+ box-shadow: var(--_shadow-hover);
306
+ }
307
+
308
+ :host([detail="minimal"]) .story-card:focus-visible {
309
+ outline: 2px solid var(--_accent);
310
+ outline-offset: 2px;
311
+ }
312
+
313
+ :host([detail="minimal"]) .story-id {
314
+ display: block;
315
+ margin-bottom: var(--_space-2xs);
316
+ }
317
+
318
+ :host([detail="minimal"]) .benefit-text {
319
+ display: none;
320
+ }
321
+
322
+ /* Compact detail level — hide empty sections */
323
+ :host([detail="compact"]) .section[data-empty] {
324
+ display: none;
325
+ }
326
+
327
+ :host([detail="compact"]) .slot-fallback {
328
+ display: none;
329
+ }
330
+ `;
331
+
332
+ export { styles };
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: "Work Item Specification"
3
+ component: work-item
4
+ version: 1.0.0
5
+ status: stable
6
+ ---
7
+
8
+ # Work Item
9
+
10
+ General-purpose work unit card for tasks, bugs, chores, spikes, and features.
11
+
12
+ ## Purpose
13
+
14
+ The engineering sibling of `<user-story>`. While user stories express product needs in agile format ("As a... I want... so that..."), work items represent the engineering work that implements those stories — or standalone work that doesn't map to any story (tech debt, bugs, ops, research).
15
+
16
+ Part of the **UX Planning Pack**. Works as a child of `<kanban-board>`, `<story-map>`, `<impact-effort>`, or standalone.
17
+
18
+ ## Static HTML Form
19
+
20
+ ```html
21
+ <work-item
22
+ item-id="PROJ-42"
23
+ title="Implement search API"
24
+ type="task"
25
+ status="in-progress"
26
+ priority="high"
27
+ assignee="Sarah Chen"
28
+ estimate="5"
29
+ story-ids="PROJ-101,PROJ-102">
30
+ <p slot="description">Build the search endpoint.</p>
31
+ <ul slot="checklist">
32
+ <li>Schema design</li>
33
+ <li>Implementation</li>
34
+ <li>Tests</li>
35
+ </ul>
36
+ </work-item>
37
+ ```
38
+
39
+ ## Attributes
40
+
41
+ | Attribute | Type | Default | Description |
42
+ |-----------|------|---------|-------------|
43
+ | `item-id` | string | — | Unique identifier (also sets HTML `id`) |
44
+ | `title` | string | — | Work item title |
45
+ | `type` | string | `"task"` | `task`, `bug`, `chore`, `spike`, `feature` |
46
+ | `priority` | string | `"medium"` | `critical`, `high`, `medium`, `low` |
47
+ | `status` | string | `"backlog"` | `backlog`, `to-do`, `in-progress`, `review`, `done`, `blocked` |
48
+ | `estimate` | string | — | Effort estimate |
49
+ | `assignee` | string | — | Assignee name (shown with avatar) |
50
+ | `story-ids` | string | — | Comma-separated linked story IDs |
51
+ | `detail` | string | `"full"` | `full`, `compact`, `minimal` |
52
+ | `compact` | boolean | — | Alias for `detail="compact"` |
53
+ | `src` | string | — | JSON data URL |
54
+
55
+ ## Slots
56
+
57
+ | Slot | Description |
58
+ |------|-------------|
59
+ | `description` | Work item description |
60
+ | `checklist` | Subtasks or checklist |
61
+ | `notes` | Additional notes |
62
+
63
+ ## Events
64
+
65
+ | Event | Detail |
66
+ |-------|--------|
67
+ | `work-item:ready` | `{ itemId, title, type, priority, status }` |
68
+ | `work-item:status` | `{ status, itemId }` |
69
+ | `work-item:priority` | `{ priority, itemId }` |
70
+
71
+ ## Item Types
72
+
73
+ | Type | Icon | Use Case |
74
+ |------|------|----------|
75
+ | `task` | Checkbox square | Engineering implementation work |
76
+ | `bug` | Bug icon | Defect that needs fixing |
77
+ | `chore` | Wrench | Tech debt, maintenance, ops |
78
+ | `spike` | Lightbulb | Research, investigation, PoC |
79
+ | `feature` | Circle check | New user-facing capability |
80
+
81
+ ## Cross-References
82
+
83
+ - `story-ids` links to `<user-story>` elements via fragment anchors
84
+ - `item-id` is auto-set as the HTML `id` for inbound cross-referencing
85
+ - Can be referenced by `<gantt-chart>` via `data-task-id` matching `item-id`
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "../../../schemas/api.schema.json",
3
+ "element": "work-item",
4
+ "type": "web-component",
5
+ "description": "General-purpose work unit card — tasks, bugs, chores, spikes, and features with slotted title, status, priority, assignee, and linked stories",
6
+ "htmlvalidate": { "flow": true, "permittedContent": ["@flow"] },
7
+ "attributes": [
8
+ { "name": "item-id", "kind": "host-api", "purpose": "config", "type": "string", "description": "Unique work item identifier, auto-sets HTML id" },
9
+ { "name": "type", "kind": "host-api", "purpose": "config", "type": "string", "description": "Item type: task | bug | chore | spike | feature" },
10
+ { "name": "priority", "kind": "host-api", "purpose": "config", "type": "string", "description": "Priority: critical | high | medium | low" },
11
+ { "name": "status", "kind": "host-api", "purpose": "config", "type": "string", "description": "Status: backlog | to-do | in-progress | review | done | blocked" },
12
+ { "name": "estimate", "kind": "host-api", "purpose": "config", "type": "string", "description": "Effort estimate (points, hours, t-shirt size)" },
13
+ { "name": "assignee", "kind": "host-api", "purpose": "config", "type": "string", "description": "Assignee name" },
14
+ { "name": "story-ids", "kind": "host-api", "purpose": "config", "type": "string", "description": "Comma-separated linked user-story IDs" },
15
+ { "name": "detail", "kind": "host-api", "purpose": "config", "type": "string", "description": "Detail level: full | compact | minimal" },
16
+ { "name": "compact", "kind": "host-api", "purpose": "config", "type": "boolean", "description": "Alias for detail=compact" },
17
+ { "name": "src", "kind": "host-api", "purpose": "config", "type": "string", "description": "URL to JSON data" }
18
+ ],
19
+ "slots": [
20
+ { "name": "title", "description": "Work item heading (e.g., <h3>)" },
21
+ { "name": "description", "description": "Work item description (e.g., <p>)" },
22
+ { "name": "checklist", "description": "Checklist or subtasks (e.g., <ul>)" },
23
+ { "name": "notes", "description": "Additional notes (e.g., <p>)" }
24
+ ],
25
+ "events": [
26
+ { "name": "work-item:ready", "detail": "{ itemId, title, type, priority, status }", "description": "Fired after render" },
27
+ { "name": "work-item:status", "detail": "{ status, itemId }", "description": "Fired when status changes" },
28
+ { "name": "work-item:priority", "detail": "{ priority, itemId }", "description": "Fired when priority changes" }
29
+ ]
30
+ }