@easyops-cn/a2ui-react 0.0.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 (161) hide show
  1. package/.claude/commands/speckit.analyze.md +184 -0
  2. package/.claude/commands/speckit.checklist.md +294 -0
  3. package/.claude/commands/speckit.clarify.md +181 -0
  4. package/.claude/commands/speckit.constitution.md +82 -0
  5. package/.claude/commands/speckit.implement.md +135 -0
  6. package/.claude/commands/speckit.plan.md +89 -0
  7. package/.claude/commands/speckit.specify.md +256 -0
  8. package/.claude/commands/speckit.tasks.md +137 -0
  9. package/.claude/commands/speckit.taskstoissues.md +30 -0
  10. package/.github/workflows/deploy.yml +69 -0
  11. package/.husky/pre-commit +1 -0
  12. package/.prettierignore +4 -0
  13. package/.prettierrc +7 -0
  14. package/.specify/memory/constitution.md +73 -0
  15. package/.specify/scripts/bash/check-prerequisites.sh +166 -0
  16. package/.specify/scripts/bash/common.sh +156 -0
  17. package/.specify/scripts/bash/create-new-feature.sh +297 -0
  18. package/.specify/scripts/bash/setup-plan.sh +61 -0
  19. package/.specify/scripts/bash/update-agent-context.sh +799 -0
  20. package/.specify/templates/agent-file-template.md +28 -0
  21. package/.specify/templates/checklist-template.md +40 -0
  22. package/.specify/templates/plan-template.md +105 -0
  23. package/.specify/templates/spec-template.md +115 -0
  24. package/.specify/templates/tasks-template.md +250 -0
  25. package/CLAUDE.md +105 -0
  26. package/CONTRIBUTING.md +97 -0
  27. package/README.md +126 -0
  28. package/components.json +21 -0
  29. package/eslint.config.js +25 -0
  30. package/netlify.toml +50 -0
  31. package/package.json +94 -0
  32. package/playground/README.md +75 -0
  33. package/playground/index.html +22 -0
  34. package/playground/package.json +32 -0
  35. package/playground/public/favicon.svg +8 -0
  36. package/playground/src/App.css +256 -0
  37. package/playground/src/App.tsx +115 -0
  38. package/playground/src/assets/react.svg +1 -0
  39. package/playground/src/components/ErrorDisplay.tsx +13 -0
  40. package/playground/src/components/ExampleSelector.tsx +64 -0
  41. package/playground/src/components/Header.tsx +47 -0
  42. package/playground/src/components/JsonEditor.tsx +32 -0
  43. package/playground/src/components/Preview.tsx +78 -0
  44. package/playground/src/components/ThemeToggle.tsx +19 -0
  45. package/playground/src/data/examples.ts +1571 -0
  46. package/playground/src/hooks/useTheme.ts +55 -0
  47. package/playground/src/index.css +220 -0
  48. package/playground/src/main.tsx +10 -0
  49. package/playground/tsconfig.app.json +34 -0
  50. package/playground/tsconfig.json +13 -0
  51. package/playground/tsconfig.node.json +26 -0
  52. package/playground/vite.config.ts +31 -0
  53. package/specs/001-a2ui-renderer/checklists/requirements.md +41 -0
  54. package/specs/001-a2ui-renderer/data-model.md +140 -0
  55. package/specs/001-a2ui-renderer/plan.md +123 -0
  56. package/specs/001-a2ui-renderer/quickstart.md +141 -0
  57. package/specs/001-a2ui-renderer/research.md +140 -0
  58. package/specs/001-a2ui-renderer/spec.md +165 -0
  59. package/specs/001-a2ui-renderer/tasks.md +310 -0
  60. package/specs/002-playground/checklists/requirements.md +37 -0
  61. package/specs/002-playground/contracts/components.md +120 -0
  62. package/specs/002-playground/data-model.md +149 -0
  63. package/specs/002-playground/plan.md +73 -0
  64. package/specs/002-playground/quickstart.md +158 -0
  65. package/specs/002-playground/research.md +117 -0
  66. package/specs/002-playground/spec.md +109 -0
  67. package/specs/002-playground/tasks.md +224 -0
  68. package/src/0.8/A2UIRender.test.tsx +793 -0
  69. package/src/0.8/A2UIRender.tsx +142 -0
  70. package/src/0.8/components/ComponentRenderer.test.tsx +373 -0
  71. package/src/0.8/components/ComponentRenderer.tsx +163 -0
  72. package/src/0.8/components/UnknownComponent.tsx +49 -0
  73. package/src/0.8/components/display/AudioPlayerComponent.tsx +37 -0
  74. package/src/0.8/components/display/DividerComponent.tsx +23 -0
  75. package/src/0.8/components/display/IconComponent.tsx +137 -0
  76. package/src/0.8/components/display/ImageComponent.tsx +57 -0
  77. package/src/0.8/components/display/TextComponent.tsx +56 -0
  78. package/src/0.8/components/display/VideoComponent.tsx +31 -0
  79. package/src/0.8/components/display/display.test.tsx +660 -0
  80. package/src/0.8/components/display/index.ts +10 -0
  81. package/src/0.8/components/index.ts +14 -0
  82. package/src/0.8/components/interactive/ButtonComponent.tsx +44 -0
  83. package/src/0.8/components/interactive/CheckBoxComponent.tsx +45 -0
  84. package/src/0.8/components/interactive/DateTimeInputComponent.tsx +176 -0
  85. package/src/0.8/components/interactive/MultipleChoiceComponent.tsx +157 -0
  86. package/src/0.8/components/interactive/SliderComponent.tsx +53 -0
  87. package/src/0.8/components/interactive/TextFieldComponent.tsx +65 -0
  88. package/src/0.8/components/interactive/index.ts +10 -0
  89. package/src/0.8/components/interactive/interactive.test.tsx +618 -0
  90. package/src/0.8/components/layout/CardComponent.tsx +30 -0
  91. package/src/0.8/components/layout/ColumnComponent.tsx +93 -0
  92. package/src/0.8/components/layout/ListComponent.tsx +81 -0
  93. package/src/0.8/components/layout/ModalComponent.tsx +41 -0
  94. package/src/0.8/components/layout/RowComponent.tsx +94 -0
  95. package/src/0.8/components/layout/TabsComponent.tsx +59 -0
  96. package/src/0.8/components/layout/index.ts +10 -0
  97. package/src/0.8/components/layout/layout.test.tsx +558 -0
  98. package/src/0.8/contexts/A2UIProvider.test.tsx +226 -0
  99. package/src/0.8/contexts/A2UIProvider.tsx +54 -0
  100. package/src/0.8/contexts/ActionContext.test.tsx +242 -0
  101. package/src/0.8/contexts/ActionContext.tsx +105 -0
  102. package/src/0.8/contexts/ComponentsMapContext.tsx +125 -0
  103. package/src/0.8/contexts/DataModelContext.test.tsx +335 -0
  104. package/src/0.8/contexts/DataModelContext.tsx +184 -0
  105. package/src/0.8/contexts/SurfaceContext.test.tsx +339 -0
  106. package/src/0.8/contexts/SurfaceContext.tsx +197 -0
  107. package/src/0.8/hooks/useA2UIMessageHandler.test.tsx +399 -0
  108. package/src/0.8/hooks/useA2UIMessageHandler.ts +123 -0
  109. package/src/0.8/hooks/useComponent.test.tsx +148 -0
  110. package/src/0.8/hooks/useComponent.ts +39 -0
  111. package/src/0.8/hooks/useDataBinding.test.tsx +334 -0
  112. package/src/0.8/hooks/useDataBinding.ts +99 -0
  113. package/src/0.8/hooks/useDispatchAction.test.tsx +83 -0
  114. package/src/0.8/hooks/useDispatchAction.ts +35 -0
  115. package/src/0.8/hooks/useSurface.test.tsx +114 -0
  116. package/src/0.8/hooks/useSurface.ts +34 -0
  117. package/src/0.8/index.ts +38 -0
  118. package/src/0.8/schemas/client_to_server.json +50 -0
  119. package/src/0.8/schemas/server_to_client.json +148 -0
  120. package/src/0.8/schemas/standard_catalog_definition.json +661 -0
  121. package/src/0.8/types/index.ts +448 -0
  122. package/src/0.8/utils/dataBinding.test.ts +443 -0
  123. package/src/0.8/utils/dataBinding.ts +212 -0
  124. package/src/0.8/utils/pathUtils.test.ts +353 -0
  125. package/src/0.8/utils/pathUtils.ts +200 -0
  126. package/src/components/ui/button.tsx +62 -0
  127. package/src/components/ui/calendar.tsx +220 -0
  128. package/src/components/ui/card.tsx +92 -0
  129. package/src/components/ui/checkbox.tsx +30 -0
  130. package/src/components/ui/dialog.tsx +141 -0
  131. package/src/components/ui/input.tsx +21 -0
  132. package/src/components/ui/label.tsx +22 -0
  133. package/src/components/ui/native-select.tsx +53 -0
  134. package/src/components/ui/popover.tsx +46 -0
  135. package/src/components/ui/select.tsx +188 -0
  136. package/src/components/ui/separator.tsx +26 -0
  137. package/src/components/ui/slider.tsx +61 -0
  138. package/src/components/ui/tabs.tsx +64 -0
  139. package/src/components/ui/textarea.tsx +18 -0
  140. package/src/index.ts +1 -0
  141. package/src/lib/utils.ts +6 -0
  142. package/tsconfig.json +28 -0
  143. package/vite.config.ts +29 -0
  144. package/vitest.config.ts +22 -0
  145. package/vitest.setup.ts +8 -0
  146. package/website/README.md +4 -0
  147. package/website/assets/favicon.svg +8 -0
  148. package/website/content/.gitkeep +0 -0
  149. package/website/content/index.md +122 -0
  150. package/website/global.d.ts +9 -0
  151. package/website/package.json +17 -0
  152. package/website/plain.config.js +28 -0
  153. package/website/serve.json +6 -0
  154. package/website/src/client/color-mode-switch.css +47 -0
  155. package/website/src/client/index.js +61 -0
  156. package/website/src/client/moon.svg +1 -0
  157. package/website/src/client/sun.svg +1 -0
  158. package/website/src/components/Footer.jsx +9 -0
  159. package/website/src/components/Header.jsx +44 -0
  160. package/website/src/components/Page.jsx +28 -0
  161. package/website/src/global.css +423 -0
@@ -0,0 +1,310 @@
1
+ # Tasks: A2UIRenderer Component Library
2
+
3
+ **Input**: Design documents from `/specs/001-a2ui-renderer/`
4
+ **Prerequisites**: plan.md, spec.md, research.md, data-model.md, quickstart.md
5
+
6
+ **Tests**: Tests are included as the existing codebase has test coverage patterns established.
7
+
8
+ **Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
9
+
10
+ ## Format: `[ID] [P?] [Story] Description`
11
+
12
+ - **[P]**: Can run in parallel (different files, no dependencies)
13
+ - **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
14
+ - Include exact file paths in descriptions
15
+
16
+ ## Path Conventions
17
+
18
+ - **Single library project**: `src/0.8/` at repository root
19
+ - Tests co-located with source files (e.g., `A2UIRender.test.tsx`)
20
+
21
+ ---
22
+
23
+ ## Phase 1: Setup (Shared Infrastructure)
24
+
25
+ **Purpose**: Create the public API entry point and foundational exports
26
+
27
+ - [x] T001 Create index.ts public API exports file in src/0.8/index.ts
28
+ - [x] T002 Export A2UIMessage type from src/0.8/index.ts
29
+ - [x] T003 Export ActionPayload as A2UIAction type alias from src/0.8/index.ts
30
+ - [x] T004 [P] Export useDispatchAction hook from src/0.8/index.ts
31
+ - [x] T005 [P] Export useDataBinding hook from src/0.8/index.ts
32
+ - [x] T006 [P] Export useFormBinding hook from src/0.8/index.ts
33
+ - [x] T007 [P] Export ComponentRenderer component from src/0.8/index.ts
34
+
35
+ ---
36
+
37
+ ## Phase 2: Foundational (Blocking Prerequisites)
38
+
39
+ **Purpose**: Create ComponentsMap context for custom component support
40
+
41
+ **⚠️ CRITICAL**: User stories 3-4 depend on this phase for custom component support
42
+
43
+ - [x] T008 Create ComponentsMapContext in src/0.8/contexts/ComponentsMapContext.tsx
44
+ - [x] T009 Add ComponentsMapProvider to wrap component rendering
45
+ - [x] T010 Update ComponentRenderer to use ComponentsMapContext for component lookup in src/0.8/components/ComponentRenderer.tsx
46
+ - [x] T011 Add dev-mode placeholder component for unknown types in src/0.8/components/UnknownComponent.tsx
47
+ - [x] T012 Update ComponentRenderer to render UnknownComponent in dev mode, skip in production
48
+
49
+ **Checkpoint**: Foundation ready - A2UIRender component can now be implemented
50
+
51
+ ---
52
+
53
+ ## Phase 3: User Story 1 - Basic Message Rendering (Priority: P1) 🎯 MVP
54
+
55
+ **Goal**: Render A2UI messages using the A2UIRender component
56
+
57
+ **Independent Test**: Pass an array of A2UIMessage objects to A2UIRender and verify the UI renders correctly
58
+
59
+ ### Tests for User Story 1
60
+
61
+ - [x] T013 [P] [US1] Create test file src/0.8/A2UIRender.test.tsx with test setup
62
+ - [x] T014 [P] [US1] Add test: renders nothing for empty messages array
63
+ - [x] T015 [P] [US1] Add test: renders components from valid A2UIMessage objects
64
+ - [x] T016 [P] [US1] Add test: renders nested components correctly
65
+
66
+ ### Implementation for User Story 1
67
+
68
+ - [x] T017 [US1] Create A2UIRender component in src/0.8/A2UIRender.tsx
69
+ - [x] T018 [US1] Implement messages prop handling with useA2UIMessageHandler
70
+ - [x] T019 [US1] Implement surface rendering loop (render all surfaces from context)
71
+ - [x] T020 [US1] Add null/undefined messages handling (graceful empty render)
72
+ - [x] T021 [US1] Export A2UIRender from src/0.8/index.ts
73
+
74
+ **Checkpoint**: User Story 1 complete - basic rendering works independently
75
+
76
+ ---
77
+
78
+ ## Phase 4: User Story 2 - Action Handling (Priority: P1)
79
+
80
+ **Goal**: Receive action callbacks when users interact with components
81
+
82
+ **Independent Test**: Click interactive components and verify onAction callback receives correct A2UIAction payload
83
+
84
+ ### Tests for User Story 2
85
+
86
+ - [x] T022 [P] [US2] Add test: onAction callback invoked when button clicked
87
+ - [x] T023 [P] [US2] Add test: action payload contains surfaceId, componentId, and context
88
+ - [x] T024 [P] [US2] Add test: multiple components dispatch unique actions
89
+
90
+ ### Implementation for User Story 2
91
+
92
+ - [x] T025 [US2] Add onAction prop to A2UIRender component in src/0.8/A2UIRender.tsx
93
+ - [x] T026 [US2] Pass onAction to A2UIProvider in A2UIRender
94
+ - [x] T027 [US2] Add test: no error when action dispatched without onAction callback
95
+
96
+ **Checkpoint**: User Stories 1 AND 2 complete - rendering and actions work
97
+
98
+ ---
99
+
100
+ ## Phase 5: User Story 3 - Custom Component Override (Priority: P2)
101
+
102
+ **Goal**: Override default components with custom implementations via ComponentsMap
103
+
104
+ **Independent Test**: Provide ComponentsMap with custom Button and verify it renders instead of default
105
+
106
+ ### Tests for User Story 3
107
+
108
+ - [x] T028 [P] [US3] Add test: custom Button component renders instead of default
109
+ - [x] T029 [P] [US3] Add test: multiple custom components render correctly
110
+ - [x] T030 [P] [US3] Add test: non-overridden components use defaults
111
+
112
+ ### Implementation for User Story 3
113
+
114
+ - [x] T031 [US3] Add components prop (ComponentsMap) to A2UIRender in src/0.8/A2UIRender.tsx
115
+ - [x] T032 [US3] Wrap rendering with ComponentsMapProvider passing custom components
116
+ - [x] T033 [US3] Merge custom components with defaults in ComponentsMapContext
117
+
118
+ **Checkpoint**: User Story 3 complete - custom component overrides work
119
+
120
+ ---
121
+
122
+ ## Phase 6: User Story 4 - Custom Component Creation (Priority: P2)
123
+
124
+ **Goal**: Add new custom component types that don't exist in defaults
125
+
126
+ **Independent Test**: Add new "Switch" component type to ComponentsMap and verify it renders
127
+
128
+ ### Tests for User Story 4
129
+
130
+ - [x] T034 [P] [US4] Add test: new component type "Switch" renders from ComponentsMap
131
+ - [x] T035 [P] [US4] Add test: custom component can use useDispatchAction hook
132
+
133
+ ### Implementation for User Story 4
134
+
135
+ - [x] T036 [US4] Ensure ComponentsMapContext supports adding new types (not just overrides)
136
+ - [x] T037 [US4] Verify useDispatchAction works in custom components (integration test)
137
+
138
+ **Checkpoint**: User Story 4 complete - extensibility works
139
+
140
+ ---
141
+
142
+ ## Phase 7: User Story 5 - Data Binding in Custom Components (Priority: P3)
143
+
144
+ **Goal**: Use useDataBinding hook in custom components to read dynamic values
145
+
146
+ **Independent Test**: Create custom component using useDataBinding and verify it displays bound value
147
+
148
+ ### Tests for User Story 5
149
+
150
+ - [x] T038 [P] [US5] Add test: custom component with useDataBinding displays bound value
151
+ - [x] T039 [P] [US5] Add test: useDataBinding returns default when path not found
152
+
153
+ ### Implementation for User Story 5
154
+
155
+ - [x] T040 [US5] Verify useDataBinding is exported from index.ts (already done in T005)
156
+ - [x] T041 [US5] Add integration test with custom component using useDataBinding
157
+
158
+ **Checkpoint**: User Story 5 complete - data binding works in custom components
159
+
160
+ ---
161
+
162
+ ## Phase 8: User Story 6 - Form Binding in Custom Components (Priority: P3)
163
+
164
+ **Goal**: Use useFormBinding hook for two-way data binding in form inputs
165
+
166
+ **Independent Test**: Create custom Switch component using useFormBinding and verify value changes
167
+
168
+ ### Tests for User Story 6
169
+
170
+ - [x] T042 [P] [US6] Add test: custom component with useFormBinding displays current value
171
+ - [x] T043 [P] [US6] Add test: useFormBinding setValue updates the bound value
172
+ - [x] T044 [P] [US6] Add test: useFormBinding returns default when path not found
173
+
174
+ ### Implementation for User Story 6
175
+
176
+ - [x] T045 [US6] Verify useFormBinding is exported from index.ts (already done in T006)
177
+ - [x] T046 [US6] Add integration test with custom Switch component using useFormBinding
178
+
179
+ **Checkpoint**: User Story 6 complete - form binding works in custom components
180
+
181
+ ---
182
+
183
+ ## Phase 9: Polish & Cross-Cutting Concerns
184
+
185
+ **Purpose**: Final validation and documentation
186
+
187
+ - [x] T047 [P] Verify all exports match README.md usage examples
188
+ - [x] T048 [P] Run full test suite and ensure all tests pass
189
+ - [ ] T049 [P] Verify build succeeds with `npm run build`
190
+ - [ ] T050 Run quickstart.md validation - test all code examples work
191
+ - [ ] T051 Update README.md if any API changes needed
192
+
193
+ ---
194
+
195
+ ## Dependencies & Execution Order
196
+
197
+ ### Phase Dependencies
198
+
199
+ - **Setup (Phase 1)**: No dependencies - can start immediately
200
+ - **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS user stories 3-4
201
+ - **User Story 1 (Phase 3)**: Depends on Setup (Phase 1) only
202
+ - **User Story 2 (Phase 4)**: Depends on User Story 1 (needs A2UIRender component)
203
+ - **User Story 3 (Phase 5)**: Depends on Foundational (Phase 2) for ComponentsMapContext
204
+ - **User Story 4 (Phase 6)**: Depends on User Story 3 (extends ComponentsMap support)
205
+ - **User Story 5 (Phase 7)**: Depends on Setup (Phase 1) - hooks already exist
206
+ - **User Story 6 (Phase 8)**: Depends on Setup (Phase 1) - hooks already exist
207
+ - **Polish (Phase 9)**: Depends on all user stories being complete
208
+
209
+ ### User Story Dependencies
210
+
211
+ ```
212
+ Phase 1 (Setup)
213
+
214
+ ├──────────────────────────────────┐
215
+ │ │
216
+ ▼ ▼
217
+ Phase 2 (Foundational) Phase 3 (US1: Basic Rendering)
218
+ │ │
219
+ │ ▼
220
+ │ Phase 4 (US2: Action Handling)
221
+ │ │
222
+ ▼ │
223
+ Phase 5 (US3: Custom Override) ◄───────┘
224
+
225
+
226
+ Phase 6 (US4: Custom Creation)
227
+
228
+ ├──────────────────────────────────┐
229
+ │ │
230
+ ▼ ▼
231
+ Phase 7 (US5: Data Binding) Phase 8 (US6: Form Binding)
232
+ │ │
233
+ └──────────────────────────────────┘
234
+
235
+
236
+ Phase 9 (Polish)
237
+ ```
238
+
239
+ ### Parallel Opportunities
240
+
241
+ **Within Phase 1 (Setup)**:
242
+
243
+ - T004, T005, T006, T007 can run in parallel (different exports)
244
+
245
+ **Within Phase 3 (US1)**:
246
+
247
+ - T013, T014, T015, T016 can run in parallel (different test cases)
248
+
249
+ **Within Phase 4 (US2)**:
250
+
251
+ - T022, T023, T024 can run in parallel (different test cases)
252
+
253
+ **Within Phase 5 (US3)**:
254
+
255
+ - T028, T029, T030 can run in parallel (different test cases)
256
+
257
+ **Within Phase 7 & 8 (US5 & US6)**:
258
+
259
+ - These phases can run in parallel with each other (independent hooks)
260
+
261
+ ---
262
+
263
+ ## Parallel Example: Phase 1 Setup
264
+
265
+ ```bash
266
+ # Launch all export tasks together:
267
+ Task: "Export useDispatchAction hook from src/0.8/index.ts"
268
+ Task: "Export useDataBinding hook from src/0.8/index.ts"
269
+ Task: "Export useFormBinding hook from src/0.8/index.ts"
270
+ Task: "Export ComponentRenderer component from src/0.8/index.ts"
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Implementation Strategy
276
+
277
+ ### MVP First (User Stories 1 + 2 Only)
278
+
279
+ 1. Complete Phase 1: Setup (index.ts exports)
280
+ 2. Complete Phase 3: User Story 1 (basic rendering)
281
+ 3. Complete Phase 4: User Story 2 (action handling)
282
+ 4. **STOP and VALIDATE**: Test basic rendering with actions
283
+ 5. Deploy/demo if ready - this covers the primary README.md example
284
+
285
+ ### Incremental Delivery
286
+
287
+ 1. Setup → US1 → US2 → **MVP Ready** (basic usage works)
288
+ 2. Add Foundational → US3 → US4 → **Customization Ready** (ComponentsMap works)
289
+ 3. Add US5 → US6 → **Full Feature Set** (all hooks work in custom components)
290
+ 4. Polish → **Production Ready**
291
+
292
+ ### Parallel Team Strategy
293
+
294
+ With multiple developers:
295
+
296
+ 1. Developer A: Phase 1 + Phase 3 + Phase 4 (core rendering path)
297
+ 2. Developer B: Phase 2 + Phase 5 + Phase 6 (customization path)
298
+ 3. Developer C: Phase 7 + Phase 8 (hook integration tests)
299
+ 4. All: Phase 9 (polish)
300
+
301
+ ---
302
+
303
+ ## Notes
304
+
305
+ - [P] tasks = different files, no dependencies
306
+ - [Story] label maps task to specific user story for traceability
307
+ - Most infrastructure already exists - tasks focus on integration and public API
308
+ - Existing tests provide patterns to follow
309
+ - Commit after each task or logical group
310
+ - Stop at any checkpoint to validate story independently
@@ -0,0 +1,37 @@
1
+ # Specification Quality Checklist: A2UI Playground
2
+
3
+ **Purpose**: Validate specification completeness and quality before proceeding to planning
4
+ **Created**: 2026-01-10
5
+ **Feature**: [spec.md](../spec.md)
6
+
7
+ ## Content Quality
8
+
9
+ - [x] No implementation details (languages, frameworks, APIs)
10
+ - [x] Focused on user value and business needs
11
+ - [x] Written for non-technical stakeholders
12
+ - [x] All mandatory sections completed
13
+
14
+ ## Requirement Completeness
15
+
16
+ - [x] No [NEEDS CLARIFICATION] markers remain
17
+ - [x] Requirements are testable and unambiguous
18
+ - [x] Success criteria are measurable
19
+ - [x] Success criteria are technology-agnostic (no implementation details)
20
+ - [x] All acceptance scenarios are defined
21
+ - [x] Edge cases are identified
22
+ - [x] Scope is clearly bounded
23
+ - [x] Dependencies and assumptions identified
24
+
25
+ ## Feature Readiness
26
+
27
+ - [x] All functional requirements have clear acceptance criteria
28
+ - [x] User scenarios cover primary flows
29
+ - [x] Feature meets measurable outcomes defined in Success Criteria
30
+ - [x] No implementation details leak into specification
31
+
32
+ ## Notes
33
+
34
+ - All checklist items pass validation
35
+ - Spec is ready for `/speckit.clarify` or `/speckit.plan`
36
+ - The specification assumes desktop-first design (1024px+) as documented in Assumptions
37
+ - JSON editor library choice is intentionally left as implementation detail
@@ -0,0 +1,120 @@
1
+ # Component Contracts: A2UI Playground
2
+
3
+ **Feature**: 002-playground
4
+ **Date**: 2026-01-10
5
+
6
+ This is a client-side only application with no external API contracts. This document defines the internal component interfaces.
7
+
8
+ ## Component Props Interfaces
9
+
10
+ ### Header
11
+
12
+ ```typescript
13
+ interface HeaderProps {
14
+ title: string
15
+ children?: React.ReactNode // For theme toggle slot
16
+ }
17
+ ```
18
+
19
+ ### ThemeToggle
20
+
21
+ ```typescript
22
+ interface ThemeToggleProps {
23
+ theme: 'light' | 'dark'
24
+ onToggle: () => void
25
+ }
26
+ ```
27
+
28
+ ### JsonEditor
29
+
30
+ ```typescript
31
+ interface JsonEditorProps {
32
+ value: string
33
+ onChange: (value: string) => void
34
+ theme?: 'light' | 'dark'
35
+ }
36
+ ```
37
+
38
+ ### Preview
39
+
40
+ ```typescript
41
+ interface PreviewProps {
42
+ messages: A2UIMessage[] | null
43
+ error: string | null
44
+ onAction?: (action: A2UIAction) => void
45
+ }
46
+ ```
47
+
48
+ ### ExampleSelector
49
+
50
+ ```typescript
51
+ interface ExampleSelectorProps {
52
+ examples: Example[]
53
+ selectedId: string
54
+ onSelect: (id: string) => void
55
+ }
56
+ ```
57
+
58
+ ### ErrorDisplay
59
+
60
+ ```typescript
61
+ interface ErrorDisplayProps {
62
+ title?: string
63
+ message: string
64
+ }
65
+ ```
66
+
67
+ ## Hook Interfaces
68
+
69
+ ### useTheme
70
+
71
+ ```typescript
72
+ function useTheme(): {
73
+ theme: 'light' | 'dark'
74
+ toggleTheme: () => void
75
+ setTheme: (theme: 'light' | 'dark') => void
76
+ }
77
+ ```
78
+
79
+ ## Data Interfaces
80
+
81
+ ### Example
82
+
83
+ ```typescript
84
+ interface Example {
85
+ id: string
86
+ title: string
87
+ description: string
88
+ messages: A2UIMessage[]
89
+ }
90
+ ```
91
+
92
+ ## Event Contracts
93
+
94
+ ### Editor Change Event
95
+
96
+ ```typescript
97
+ // Triggered when user edits JSON in editor
98
+ type EditorChangeHandler = (newValue: string) => void
99
+ ```
100
+
101
+ ### Example Select Event
102
+
103
+ ```typescript
104
+ // Triggered when user selects an example from dropdown
105
+ type ExampleSelectHandler = (exampleId: string) => void
106
+ ```
107
+
108
+ ### Theme Toggle Event
109
+
110
+ ```typescript
111
+ // Triggered when user clicks theme toggle
112
+ type ThemeToggleHandler = () => void
113
+ ```
114
+
115
+ ### Action Dispatch Event
116
+
117
+ ```typescript
118
+ // Triggered when A2UIRender dispatches an action
119
+ type ActionHandler = (action: A2UIAction) => void
120
+ ```
@@ -0,0 +1,149 @@
1
+ # Data Model: A2UI Playground
2
+
3
+ **Feature**: 002-playground
4
+ **Date**: 2026-01-10
5
+
6
+ ## Entities
7
+
8
+ ### Example
9
+
10
+ Represents a pre-built A2UI message configuration that users can select.
11
+
12
+ ```typescript
13
+ interface Example {
14
+ id: string // Unique identifier (e.g., "hello-world")
15
+ title: string // Display name (e.g., "Hello World")
16
+ description: string // Brief explanation of what the example demonstrates
17
+ messages: A2UIMessage[] // The A2UI messages to render
18
+ }
19
+ ```
20
+
21
+ **Validation Rules**:
22
+
23
+ - `id` must be unique across all examples
24
+ - `title` must be non-empty
25
+ - `messages` must be a valid A2UIMessage array
26
+
27
+ ### Theme
28
+
29
+ User's color scheme preference.
30
+
31
+ ```typescript
32
+ type Theme = 'light' | 'dark'
33
+ ```
34
+
35
+ **Storage**: localStorage key `'theme'`
36
+
37
+ **Default**: System preference via `prefers-color-scheme` media query
38
+
39
+ ### EditorState
40
+
41
+ Current state of the playground editor.
42
+
43
+ ```typescript
44
+ interface EditorState {
45
+ jsonContent: string // Raw JSON string in editor
46
+ parsedMessages: A2UIMessage[] | null // Parsed messages (null if invalid JSON)
47
+ parseError: string | null // Error message if JSON is invalid
48
+ selectedExampleId: string // Currently selected example ID
49
+ }
50
+ ```
51
+
52
+ **Validation Rules**:
53
+
54
+ - `jsonContent` can be any string (including invalid JSON)
55
+ - `parsedMessages` is null when JSON parsing fails
56
+ - `parseError` contains the error message when parsing fails
57
+
58
+ ## State Transitions
59
+
60
+ ### Editor Content Flow
61
+
62
+ ```
63
+ User types in editor
64
+
65
+ jsonContent updated
66
+
67
+ JSON.parse() attempted
68
+
69
+ ┌─────────────────────────────────────┐
70
+ │ Success │ Failure
71
+ │ ↓ │ ↓
72
+ │ parsedMessages = result │ parsedMessages = null
73
+ │ parseError = null │ parseError = error.message
74
+ │ ↓ │ ↓
75
+ │ A2UIRender receives messages │ ErrorDisplay shown
76
+ └─────────────────────────────────────┘
77
+ ```
78
+
79
+ ### Example Selection Flow
80
+
81
+ ```
82
+ User selects example from dropdown
83
+
84
+ selectedExampleId updated
85
+
86
+ jsonContent = JSON.stringify(example.messages, null, 2)
87
+
88
+ parsedMessages = example.messages
89
+ parseError = null
90
+
91
+ Editor and Preview both update
92
+ ```
93
+
94
+ ### Theme Toggle Flow
95
+
96
+ ```
97
+ User clicks theme toggle
98
+
99
+ Current theme read from state
100
+
101
+ New theme = (current === 'dark') ? 'light' : 'dark'
102
+
103
+ document.documentElement.dataset.theme = newTheme
104
+ localStorage.setItem('theme', newTheme)
105
+
106
+ UI re-renders with new theme
107
+ ```
108
+
109
+ ## Relationships
110
+
111
+ ```
112
+ ┌─────────────┐ selects ┌─────────────┐
113
+ │ Example │◄─────────────────│ EditorState │
114
+ └─────────────┘ └─────────────┘
115
+ │ │
116
+ │ provides │ contains
117
+ ▼ ▼
118
+ ┌─────────────┐ ┌─────────────┐
119
+ │ A2UIMessage │ │ jsonContent │
120
+ │ Array │ │ (string) │
121
+ └─────────────┘ └─────────────┘
122
+ │ │
123
+ └───────────┬───────────────────┘
124
+ │ renders
125
+
126
+ ┌─────────────┐
127
+ │ A2UIRender │
128
+ └─────────────┘
129
+ ```
130
+
131
+ ## A2UIMessage Structure (Reference)
132
+
133
+ From the main library, A2UIMessage is a union type:
134
+
135
+ ```typescript
136
+ type A2UIMessage =
137
+ | { beginRendering: { surfaceId: string; root: string; styles?: string } }
138
+ | { surfaceUpdate: { surfaceId: string; components: ComponentUpdate[] } }
139
+ | {
140
+ dataModelUpdate: {
141
+ surfaceId: string
142
+ path: string
143
+ contents: DataContent[]
144
+ }
145
+ }
146
+ | { deleteSurface: { surfaceId: string } }
147
+ ```
148
+
149
+ Examples must conform to this structure to render correctly.
@@ -0,0 +1,73 @@
1
+ # Implementation Plan: A2UI Playground
2
+
3
+ **Branch**: `002-playground` | **Date**: 2026-01-10 | **Spec**: [spec.md](./spec.md)
4
+ **Input**: Feature specification from `/specs/002-playground/spec.md`
5
+
6
+ ## Summary
7
+
8
+ Implement an interactive playground for the A2UI React library that allows developers to edit A2UI JSON messages in a code editor and see real-time rendered previews. The playground includes a header matching the website design (with theme toggle), a split-panel layout (editor left, preview right), and pre-built examples selectable via dropdown.
9
+
10
+ ## Technical Context
11
+
12
+ **Language/Version**: TypeScript 5.9, React 19
13
+ **Primary Dependencies**: @uiw/react-codemirror (CodeMirror 6), @codemirror/lang-json, @easyops-cn/a2ui-react, Tailwind CSS 4
14
+ **Storage**: localStorage (theme preference only)
15
+ **Testing**: Vitest + React Testing Library (inherited from root)
16
+ **Target Platform**: Modern browsers (Chrome, Firefox, Safari, Edge), desktop 1024px+
17
+ **Project Type**: Web application (playground workspace within monorepo)
18
+ **Performance Goals**: Preview updates within 500ms, initial load under 3 seconds
19
+ **Constraints**: Desktop-only (1024px minimum width), client-side only
20
+ **Scale/Scope**: Single-page application, 5-6 pre-built examples
21
+
22
+ ## Constitution Check
23
+
24
+ _GATE: Must pass before Phase 0 research. Re-check after Phase 1 design._
25
+
26
+ The project constitution is a template without specific rules defined. No gates to enforce.
27
+
28
+ **Status**: PASS (no violations)
29
+
30
+ ## Project Structure
31
+
32
+ ### Documentation (this feature)
33
+
34
+ ```text
35
+ specs/002-playground/
36
+ ├── plan.md # This file
37
+ ├── research.md # Phase 0 output - technology decisions
38
+ ├── data-model.md # Phase 1 output - data structures
39
+ ├── quickstart.md # Phase 1 output - development guide
40
+ └── tasks.md # Phase 2 output (created by /speckit.tasks)
41
+ ```
42
+
43
+ ### Source Code (repository root)
44
+
45
+ ```text
46
+ playground/
47
+ ├── src/
48
+ │ ├── components/
49
+ │ │ ├── Header.tsx # Header with title and theme toggle
50
+ │ │ ├── ThemeToggle.tsx # Sun/moon theme switch component
51
+ │ │ ├── JsonEditor.tsx # CodeMirror-based JSON editor
52
+ │ │ ├── Preview.tsx # A2UIRender wrapper with error boundary
53
+ │ │ ├── ExampleSelector.tsx # Dropdown for example selection
54
+ │ │ └── ErrorDisplay.tsx # Error state display component
55
+ │ ├── data/
56
+ │ │ └── examples.ts # Pre-built A2UI message examples
57
+ │ ├── hooks/
58
+ │ │ └── useTheme.ts # Theme state management with localStorage
59
+ │ ├── App.tsx # Main app with split-panel layout
60
+ │ ├── App.css # Layout and theme styles
61
+ │ ├── main.tsx # Entry point
62
+ │ └── index.css # Global styles (Tailwind)
63
+ ├── index.html
64
+ ├── package.json
65
+ ├── vite.config.ts
66
+ └── tsconfig.app.json
67
+ ```
68
+
69
+ **Structure Decision**: Single workspace application within the existing monorepo. The playground is a standalone Vite React app that imports the main library as a workspace dependency.
70
+
71
+ ## Complexity Tracking
72
+
73
+ No constitution violations to justify.