@explorer02/cfm-survey-sdk 0.2.5 → 0.2.7

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 (39) hide show
  1. package/dist/cli/index.js +45 -45
  2. package/dist/cli/index.mjs +45 -45
  3. package/package.json +1 -1
  4. package/templates/docs/00-integration/agent-execution-flow.md +18 -6
  5. package/templates/docs/00-integration/agent-operating-contract.md +2 -0
  6. package/templates/docs/00-integration/apply-ui-config.md +15 -2
  7. package/templates/docs/00-integration/component-checklist.md +5 -3
  8. package/templates/docs/00-integration/ui-customization-wizard.md +1 -1
  9. package/templates/docs/00-integration/wizard-chrome-contract.md +284 -0
  10. package/templates/docs/00-integration/wizard-config-handoff.md +7 -1
  11. package/templates/docs/00-integration/wizard-customization-catalog.md +391 -0
  12. package/templates/docs/00-integration/wizard-post-customize-build.md +405 -0
  13. package/templates/docs/00-integration/wizard-preview-build-guide.md +20 -4
  14. package/templates/docs/00-integration/wizard-question-type-styling.md +27 -6
  15. package/templates/docs/01-components/19-survey-sticky-chrome.md +16 -55
  16. package/templates/docs/03-ui-specs/README.md +1 -1
  17. package/templates/docs/MANIFEST.json +10 -1
  18. package/templates/docs/index.md +10 -7
  19. package/templates/docs/templates/Footer.tsx +72 -0
  20. package/templates/docs/templates/Header.tsx +110 -0
  21. package/templates/docs/templates/LanguageSelector.tsx +40 -0
  22. package/templates/docs/templates/PreviewBridgeInit.tsx +13 -0
  23. package/templates/docs/templates/ProgressBar.tsx +33 -0
  24. package/templates/docs/templates/Question.tsx +51 -7
  25. package/templates/docs/templates/RatingScale.tsx +66 -59
  26. package/templates/docs/templates/SurveyStickyChrome.tsx +19 -5
  27. package/templates/docs/templates/uiConfig.ts +33 -0
  28. package/templates/docs/templates/verify-agent-build.sh +31 -1
  29. package/templates/preview-harness/preview-bridge.inline.js +18 -4
  30. package/templates/preview-harness/vite-app/src/preview-live-overrides.css +7 -0
  31. package/templates/previewBridge.ts +144 -39
  32. package/templates/survey-theme.css +7 -0
  33. package/templates/wizard-dist/assets/{PreviewMock-AoZdAEPZ.js → PreviewMock-tTMvwuEy.js} +1 -1
  34. package/templates/wizard-dist/assets/{TypePanel-39FnbtvG.js → TypePanel-B9Ls7BSq.js} +1 -1
  35. package/templates/wizard-dist/assets/index-CjkIlOUI.css +1 -0
  36. package/templates/wizard-dist/assets/index-CoCrnnxt.js +34 -0
  37. package/templates/wizard-dist/index.html +2 -2
  38. package/templates/wizard-dist/assets/index-BhWM50Yu.css +0 -1
  39. package/templates/wizard-dist/assets/index-CWKdsJOp.js +0 -34
@@ -0,0 +1,405 @@
1
+ # Wizard Post-Customize Build — All Types, All Formats
2
+
3
+ > **Phase 6c runbook.** Read after the client clicks **Review & Build** and the CLI prints `✅ UI configuration saved`.
4
+ > Companion docs: [`wizard-config-handoff.md`](wizard-config-handoff.md) · [`wizard-customization-catalog.md`](wizard-customization-catalog.md) · [`apply-ui-config.md`](apply-ui-config.md) · [`wizard-question-type-styling.md`](wizard-question-type-styling.md) · [`wizard-chrome-contract.md`](wizard-chrome-contract.md)
5
+
6
+ This doc answers two agent questions:
7
+
8
+ 1. **What does the wizard expose** for every question type and format — and which component must honor it?
9
+ 2. **What is the exact build sequence** after the client confirms customization — without re-running the wizard or skipping tokens?
10
+
11
+ ---
12
+
13
+ ## End-to-end flow (confirmation → deploy)
14
+
15
+ ```mermaid
16
+ sequenceDiagram
17
+ participant Client
18
+ participant Wizard as Wizard SPA
19
+ participant CLI as cfm-sdk customize
20
+ participant Agent
21
+ participant Build as npm run build
22
+ participant Deploy as Phase 7
23
+
24
+ Client->>Wizard: Review and Build
25
+ Wizard->>CLI: POST /api/save-config
26
+ CLI->>CLI: Write survey-ui-config.json
27
+ CLI->>CLI: Delete out/previews/ (GC)
28
+ CLI->>Agent: Exit 0 — UI configuration saved
29
+ Agent->>Agent: Phase 6c apply (this doc)
30
+ Agent->>Build: verify-agent-build.sh
31
+ Build->>Agent: out/ + logo in out/
32
+ Agent->>Deploy: After INPUT 4 confirm
33
+ ```
34
+
35
+ **Agent must not** start Phase 6c until CLI exit 0. **Agent must not** proceed to Phase 7 until verify + build pass after apply.
36
+
37
+ ---
38
+
39
+ ## Phase 6c — ordered runbook (copy-paste checklist)
40
+
41
+ Run from project root after `✅ UI configuration saved`.
42
+
43
+ ### A. Capture
44
+
45
+ ```bash
46
+ # Local wizard (default)
47
+ test -f survey-ui-config.json && echo "OK: config captured"
48
+
49
+ # EC2 review mode only — also read diff before editing code
50
+ test -f survey-ui-config.final.json && cat survey-ui-config.diff.md
51
+ ```
52
+
53
+ ### B. Validate
54
+
55
+ - [ ] JSON parses; validate against `templates/survey-ui-config.schema.json`
56
+ - [ ] `surveyTypes[]` still matches fetched survey inventory (types in survey, not wizard tabs)
57
+ - [ ] EC2: every path in `survey-ui-config.diff.json` (`changed` + `added` + `removed`) has a planned apply target
58
+
59
+ ### C. Regenerate theme (full — never partial)
60
+
61
+ - [ ] Regenerate **entire** `src/styles/survey-theme.css` from final config (all `global.*` + all `questionTypes.*`)
62
+ - [ ] Confirm `@import` in `globals.css` (or equivalent)
63
+ - [ ] Theme → Question card tokens present: `--cfm-matrix-selected`, `--cfm-input-focus-ring`
64
+
65
+ ### D. Chrome + content hooks
66
+
67
+ Copy/sync if missing — see [`wizard-chrome-contract.md`](wizard-chrome-contract.md).
68
+
69
+ | Area | Config paths | Wire in |
70
+ |------|--------------|---------|
71
+ | Logo | `global.logo.fileName` | `Header.tsx` via `uiConfig.getLogoSrc()` → `src="./{fileName}"` |
72
+ | Company | `global.companyName`, `global.header.showCompanyName` | `data-cfm-company` in brand row after logo |
73
+ | Title / thank you | `global.surveyTitle`, `global.thankYouMessage` | `data-cfm-survey-title`, `data-cfm-thank-you` |
74
+ | Buttons | `global.buttons.*` | `data-cfm-btn-next`, `data-cfm-btn-back` |
75
+ | Footer | `global.footer.*` | `cfm-footer`, `data-cfm-copyright`, `data-cfm-footer-links` |
76
+ | Layout | `global.layout.*` | `SurveyPage` / `SurveyStickyChrome` conditionals |
77
+ | Progress | `global.theme.progress*` | `data-cfm-progress` + `.cfm-progress` (separate from header) |
78
+
79
+ **Logo rule:** never hand-edit `fileName` to a seed SVG. Use wizard value; file must exist in `public/{fileName}`.
80
+
81
+ ```bash
82
+ LOGO=$(python3 -c "import json; print(json.load(open('survey-ui-config.json')).get('global',{}).get('logo',{}).get('fileName') or '')")
83
+ test -z "$LOGO" || test -f "public/$LOGO" || echo "FAIL: logo file missing in public/"
84
+ ```
85
+
86
+ ### E. Per-type tokens (all wizard types — not only survey inventory)
87
+
88
+ The wizard **Question Types** step exposes **10 type families** (TEXT_AND_MEDIA uses theme vars only). Apply `questionTypes.{TYPE}` for **every** type block in saved JSON — even if the client's survey does not include that type. This keeps `survey-theme.css` complete and future-proof.
89
+
90
+ Use the format matrix below. Detailed token tables: [`wizard-customization-catalog.md`](wizard-customization-catalog.md) and [`wizard-question-type-styling.md`](wizard-question-type-styling.md) and [`apply-ui-config.md`](apply-ui-config.md).
91
+
92
+ ### F. Hook options
93
+
94
+ - [ ] `placeholders.*` → `useSurveySDK({ options: { placeholders } })` (stable ref)
95
+ - [ ] `customFields` → `customFieldValues.ts` + SurveyPage + Question prop
96
+ - [ ] `debug.enabled` → hook `debug: true`
97
+
98
+ ### G. EC2 promote (review mode only)
99
+
100
+ ```bash
101
+ npx cfm-sdk confirm-ui-config # downloads logo → public/
102
+ ```
103
+
104
+ ### H. Verify + build (blocking)
105
+
106
+ ```bash
107
+ bash templates/verify-agent-build.sh
108
+ ```
109
+
110
+ Script runs `npm run build`. Additionally confirm logo in static output:
111
+
112
+ ```bash
113
+ test -z "$LOGO" || test -f "out/$LOGO" || echo "FAIL: logo not in out/"
114
+ ```
115
+
116
+ ### I. Phase 7 gate
117
+
118
+ Only after H passes → ask deploy (INPUT 4). See [`aws-deploy.md`](aws-deploy.md) § Logos.
119
+
120
+ **Do not re-run** `npx cfm-sdk customize` unless the client explicitly requests another session.
121
+
122
+ **Do not re-run** `npx cfm-sdk export-previews` after wizard save — previews were deleted on purpose (GC). Export-previews is for **component structure changes** during Phase 5, not for applying saved config.
123
+
124
+ ---
125
+
126
+ ## Wizard steps → live preview keys
127
+
128
+ | Wizard step | Default preview | What updates live |
129
+ |-------------|-----------------|-------------------|
130
+ | **Branding & Header** | `header` | Logo upload, company name, header dimensions/colors |
131
+ | **Footer** | `footer` | Copyright, links, footer logo, colors |
132
+ | **Theme & Colors** | `survey_page` | Palette, header/footer/progress/language colors, **Question card** (cell selected + focus ring) |
133
+ | **Layout & Chrome** | `survey_page` | showHeader/Footer/Progress, nav buttons, question numbers, asterisk, width, font |
134
+ | **Question Types** | per format tab | Per-type panels (see matrix below) |
135
+ | **Testing & Tokens** | `survey_page` | Placeholders, custom fields, debug |
136
+ | **Deploy & Build** | `survey_page` | Deploy target metadata (informational) |
137
+
138
+ Chrome previews also exist: `intro`, `end`, `chrome` — used by harness; agent wires same hooks on Intro/End/SurveyPage.
139
+
140
+ ---
141
+
142
+ ## Question type format matrix (wizard → config → component)
143
+
144
+ ### How to read this table
145
+
146
+ | Column | Meaning |
147
+ |--------|---------|
148
+ | **Preview key** | Iframe loaded in wizard right panel |
149
+ | **Survey `question.type`** | Flat literal in `Question.tsx` dispatch |
150
+ | **Wizard controls** | Fields in Question Types step for that tab |
151
+ | **Config block** | `survey-ui-config.json` path (shared across formats of same type) |
152
+ | **Scale / branch** | Component that must use `var(--cfm-*)` + `selectionStyles` / `labelStyles` |
153
+ | **DOM attrs** | `data-cfm-*` set on `:root` or elements |
154
+
155
+ **Shared across almost all scale types:** Theme → Question card → `cellSelectedColor` → `--cfm-matrix-selected`; `focusRingColor` → `--cfm-input-focus-ring`. Use [`selectionStyles.ts`](../templates/selectionStyles.ts).
156
+
157
+ **Matrix multi-row:** Toggle **Preview multiple statements** on CFM, CSAT, Rating, Slider types. `LikertMatrixScale` / `CsatMatrixScale` must map **all** `statementRows` — not a single hardcoded row.
158
+
159
+ ---
160
+
161
+ ### MCQ — `questionTypes.MCQ`
162
+
163
+ | Preview key | Format | Wizard controls | Scale / branch |
164
+ |-------------|--------|-----------------|----------------|
165
+ | `MCQ_single` | Single select | Option style, gap, radius, padding | `Question.tsx` MCQ branch + radio ring/dot |
166
+ | `MCQ_multiple` | Multi select | Same | Checkbox: ring border + fill from theme |
167
+
168
+ | Config field | CSS / DOM |
169
+ |--------------|-----------|
170
+ | `optionStyle` | `data-cfm-mcq-style` on `:root` |
171
+ | `optionGap` | `--cfm-mcq-option-gap` |
172
+ | `borderRadius` | `--cfm-mcq-border-radius` |
173
+ | `optionPadding` | `--cfm-mcq-card-padding` |
174
+ | Selection | `--cfm-input-focus-ring`, `--cfm-matrix-selected`, `--cfm-mcq-selected-bg` |
175
+
176
+ ---
177
+
178
+ ### TEXTFIELD — `questionTypes.TEXTFIELD`
179
+
180
+ | Preview key | Format | Wizard controls | Scale / branch |
181
+ |-------------|--------|-----------------|----------------|
182
+ | `TEXTFIELD_short` | Short | Placeholder text, radius, border, placeholder color | `Question.tsx` + `data-cfm-textfield` |
183
+ | `TEXTFIELD_long` | Long | Same | `textarea` with same hooks |
184
+
185
+ | Config field | CSS / DOM |
186
+ |--------------|-----------|
187
+ | `inputRadius` | `--cfm-input-radius` |
188
+ | `borderColor` | `--cfm-input-border` |
189
+ | `placeholderColor` | `--cfm-input-placeholder` + `::placeholder` rule in theme CSS |
190
+ | `defaultPlaceholder` | Default placeholder string (cosmetic) |
191
+ | Focus | `--cfm-input-focus-ring` |
192
+
193
+ ---
194
+
195
+ ### NPS_SCALE — `questionTypes.NPS_SCALE`
196
+
197
+ | Preview key | Format | Wizard controls | Scale / branch |
198
+ |-------------|--------|-----------------|----------------|
199
+ | `NPS_SCALE` | Radio / numbered / pill | Button style, track colors, hint labels, number labels | `RatingScale.tsx` |
200
+
201
+ | Config field | CSS / DOM |
202
+ |--------------|-----------|
203
+ | `buttonStyle` | `data-cfm-nps-button-style` |
204
+ | `selectedFill`, `trackBarColor`, `trackHighlightColor` | `--cfm-nps-*` |
205
+ | `hintMinText`, `hintMaxText`, hint colors | `hintLabelStyle()` |
206
+ | `numberLabelMode`, per-index colors | `--cfm-number-*`, `resolveNumberLabelColor()` for **unselected** badges |
207
+ | Selection | `scaleRadioRingStyle`, `scaleRadioDotStyle` |
208
+
209
+ ---
210
+
211
+ ### CFM_MATRIX — `questionTypes.CFM_MATRIX`
212
+
213
+ Wizard tabs: **Likert**, **Bipolar**. Harness also ships `CFM_transpose`, `CFM_carousel`, `CFM_dropdown` — same config block.
214
+
215
+ | Preview key | Matrix variant | Wizard controls | Scale / branch |
216
+ |-------------|----------------|-----------------|----------------|
217
+ | `CFM_likert` | Likert grid | Row width, bipolar %, label items | `LikertMatrixScale.tsx` |
218
+ | `CFM_bipolar` | Bipolar anchors | Same + bipolar column width | Same |
219
+ | `CFM_transpose` | Transposed | *(no extra wizard fields)* | `LikertMatrixScale` / matrix utils |
220
+ | `CFM_carousel` | Carousel | Label items + theme selection | Matrix carousel branch |
221
+ | `CFM_dropdown` | Dropdown | Label items | `MatrixDropdown.tsx` |
222
+
223
+ | Config field | CSS / DOM |
224
+ |--------------|-----------|
225
+ | `rowLabelWidth` | `--cfm-matrix-row-width` |
226
+ | `bipolarColumnWidthPercent` | `--cfm-matrix-bipolar-width` |
227
+ | `columnLabelColor`, `columnLabelBgColor` | `matrixColumnLabelStyle()` |
228
+ | Selection | `matrixRadioRingStyle`, `matrixRadioDotStyle` |
229
+
230
+ **No** per-format accent overrides in wizard — Question card tokens only.
231
+
232
+ ---
233
+
234
+ ### CSAT_MATRIX — `questionTypes.CSAT_MATRIX`
235
+
236
+ | Preview key | Format | Wizard controls | Scale / branch |
237
+ |-------------|--------|-----------------|----------------|
238
+ | `CSAT_emoji` | Emoji | Emoji size, unselected opacity, label items | `CsatMatrixScale.tsx` emoji cells |
239
+ | `CSAT_star` | Star | Unselected opacity, label items | Star row; selected = `cellSelectedVar` |
240
+ | `CSAT_numbered` | Numbered | Opacity, label items, number labels | Number badges + selection pattern |
241
+ | `CSAT_graphics` | Graphics slider | Label items | `CustomSliderTrack.tsx` thumb pattern |
242
+ | `CSAT_carousel` | Carousel | Label items | Dot indicators = cell selected when active |
243
+ | `CSAT_dropdown` | Dropdown | Label items | `MatrixDropdown` + list radio |
244
+
245
+ | Config field | CSS / DOM |
246
+ |--------------|-----------|
247
+ | `emojiSize` | `--cfm-csat-emoji-size` |
248
+ | `unselectedOpacity` | `--cfm-csat-unselected-opacity` |
249
+ | `columnLabelColor`, `columnLabelBgColor` | `csatColumnLabelStyle()` |
250
+ | Number labels (numbered tab) | `--cfm-number-*` |
251
+ | Selection | theme Question card vars |
252
+
253
+ ---
254
+
255
+ ### RATING_MATRIX — `questionTypes.RATING_MATRIX`
256
+
257
+ | Preview key | Format | Wizard controls | Scale / branch |
258
+ |-------------|--------|-----------------|----------------|
259
+ | `RATING_star` | Star | Unselected star opacity, label items | `CsatMatrixScale.tsx` (shared path) |
260
+ | `RATING_numbered` | Numbered | Opacity, label items, number labels | Numbered badges |
261
+ | `RATING_radio` | Radio grid | Opacity, label items | Horizontal radio grid — `matrixRadioRingStyle` |
262
+ | `RATING_emoji` | Emoji | Emoji size, opacity, label items | Emoji cells |
263
+ | `RATING_graphics` | Graphics | Opacity, label items | `CustomSliderTrack` |
264
+ | `RATING_slider` | Slider | Label items | Slider thumb pattern |
265
+
266
+ Config block mirrors CSAT where formats overlap; uses `unselectedStarOpacity` instead of `unselectedOpacity` in JSON.
267
+
268
+ ---
269
+
270
+ ### SLIDER_MATRIX — `questionTypes.SLIDER_MATRIX`
271
+
272
+ | Preview key | Format | Wizard controls | Scale / branch |
273
+ |-------------|--------|-----------------|----------------|
274
+ | `SLIDER_matrix` | Slider matrix | Track, thumb, tick colors, row width, tick label items, tick number labels | `SliderMatrixScale.tsx`, `CustomSliderTrack.tsx` |
275
+
276
+ | Config field | CSS / DOM |
277
+ |--------------|-----------|
278
+ | `trackColor`, `thumbColor`, `tickColor` | `--cfm-slider-track`, `--cfm-slider-thumb`, `--cfm-slider-tick` |
279
+ | `rowLabelWidth` | `--cfm-matrix-row-width` |
280
+ | Tick label items | `sliderTickLabelStyle()` |
281
+ | Tick number labels | `--cfm-number-*` |
282
+ | Row band | `--cfm-slider-row-band` / `--cfm-row-band` from theme |
283
+ | Thumb selection | focus ring + cell selected on knob |
284
+
285
+ ---
286
+
287
+ ### FILE_UPLOAD — `questionTypes.FILE_UPLOAD`
288
+
289
+ | Preview key | Wizard controls | Scale / branch |
290
+ |-------------|-----------------|----------------|
291
+ | `FILE_UPLOAD` | Dropzone border style, border color, fill, padding | `FileUploadScale.tsx` |
292
+
293
+ | Config field | CSS / DOM |
294
+ |--------------|-----------|
295
+ | `dropzoneStyle` | `data-cfm-dropzone-style` |
296
+ | `borderColor` | `--cfm-upload-border-color` (not hardcoded gray) |
297
+ | `dropzoneFillColor`, `dropzonePadding` | `--cfm-upload-fill`, `--cfm-upload-padding` |
298
+ | Focus / drag | `--cfm-input-focus-ring`, `--cfm-mcq-selected-bg` |
299
+
300
+ Presigned upload flow unchanged — styling only.
301
+
302
+ ---
303
+
304
+ ### HEATMAP — `questionTypes.HEATMAP`
305
+
306
+ | Preview key | Wizard controls | Scale / branch |
307
+ |-------------|-----------------|----------------|
308
+ | `HEATMAP` | Pin color, border, size | `HeatmapScale.tsx` |
309
+
310
+ | Config field | CSS / DOM |
311
+ |--------------|-----------|
312
+ | `pinColor` | `--cfm-heatmap-pin` |
313
+ | `pinBorderColor` | `--cfm-heatmap-pin-border` |
314
+ | `pinSize` | `--cfm-heatmap-pin-size` |
315
+
316
+ ---
317
+
318
+ ### RANK_ORDER — `questionTypes.RANK_ORDER`
319
+
320
+ | Preview key | Variant | Wizard controls | Scale / branch |
321
+ |-------------|---------|-----------------|----------------|
322
+ | `RANK_drag` | Drag & drop | Item bg, handle, badge | `RankOrderScale.tsx` + `@dnd-kit` |
323
+ | `RANK_dropdown` | Dropdown | Item bg, select border, badge | Dropdown rank UI in same scale |
324
+
325
+ | Config path | CSS var |
326
+ |-------------|---------|
327
+ | `drag.itemBg` / `dropdown.itemBg` | `--cfm-rank-item-bg` |
328
+ | `drag.dragHandleColor` | `--cfm-rank-handle` |
329
+ | `*.rankBadgeColor` | `--cfm-rank-badge` |
330
+ | `drag.itemGap`, `itemPadding` | `--cfm-rank-item-gap`, `--cfm-rank-item-padding` |
331
+ | `dropdown.selectBorderColor` | `--cfm-rank-select-border` |
332
+
333
+ Do not change `interactionMode` or answer payload shapes.
334
+
335
+ ---
336
+
337
+ ### TEXT_AND_MEDIA — theme only
338
+
339
+ | Preview key | Wizard step | Tokens |
340
+ |-------------|-------------|--------|
341
+ | `TEXT_AND_MEDIA` | Theme (media) | `--cfm-media-max-width`, `--cfm-media-radius` |
342
+
343
+ No dedicated Question Types panel — wire in `Question.tsx` TEXT_AND_MEDIA branch.
344
+
345
+ ---
346
+
347
+ ## Phase 5 prerequisite — why post-customize apply works smoothly
348
+
349
+ If Phase 5 copied all wizard-ready artifacts **before** the wizard ran, Phase 6c is mostly **config sync** — not rewriting components:
350
+
351
+ | Artifact | Required before wizard |
352
+ |----------|------------------------|
353
+ | `survey-theme.css` | Full `--cfm-*` scaffold |
354
+ | `selectionStyles.ts`, `labelStyles.ts` | Selection + label helpers |
355
+ | `Header.tsx`, `Footer.tsx`, chrome templates | All `data-cfm-*` hooks |
356
+ | `uiConfig.ts` | No bare `UI_CONFIG` |
357
+ | Scale components per inventory | `var(--cfm-*)` not hardcoded hex |
358
+ | `previewBridge.ts` | `layoutFlags` handler (dev preview) |
359
+
360
+ If a wizard control does not live-update during Phase 6b, fix the **missing hook** in Phase 5 templates first — then re-run wizard. See symptom table in [`wizard-chrome-contract.md`](wizard-chrome-contract.md).
361
+
362
+ ---
363
+
364
+ ## Post-apply smoke checks (by type in survey)
365
+
366
+ For each `question.type` in the **fetched survey** (not all 11), spot-check in `npm run dev` after apply:
367
+
368
+ | Type | Check |
369
+ |------|-------|
370
+ | MCQ | Option gap/radius; selected ring uses theme focus + cell colors |
371
+ | TEXTFIELD | Placeholder color on focus/blur |
372
+ | NPS_SCALE | Number badge traffic colors when unselected; selected uses theme |
373
+ | CFM_MATRIX | Column label item colors; multi-row if multiple statements |
374
+ | CSAT / RATING | Format-specific opacity/size; carousel dots if used |
375
+ | SLIDER_MATRIX | Thumb ring+dot; tick label item colors |
376
+ | FILE_UPLOAD | Dropzone border color from config |
377
+ | HEATMAP | Pin size/color |
378
+ | RANK_ORDER | Drag handle + badge colors |
379
+ | TEXT_AND_MEDIA | Media max-width |
380
+
381
+ ---
382
+
383
+ ## Common mistakes after confirmation
384
+
385
+ | Mistake | Fix |
386
+ |---------|-----|
387
+ | Partial CSS update (only changed colors) | Full regen `survey-theme.css` from entire JSON |
388
+ | Changed `logo.fileName` manually | Use wizard `fileName`; keep `public/` file in sync |
389
+ | Re-ran `export-previews` after save | Unnecessary — previews GC'd; apply config to client app instead |
390
+ | Skipped types not in survey inventory | Still apply `questionTypes.*` blocks from saved JSON to CSS |
391
+ | Edited `Question.tsx` dispatch | Forbidden — cosmetic tokens only |
392
+ | Deploy before `out/{logo}` exists | Run build + logo preflight in Phase 6c H |
393
+
394
+ ---
395
+
396
+ ## Related
397
+
398
+ | Doc | When |
399
+ |-----|------|
400
+ | [`wizard-config-handoff.md`](wizard-config-handoff.md) | Wait protocol, GC, EC2 link |
401
+ | [`apply-ui-config.md`](apply-ui-config.md) | Full config path → CSS tables |
402
+ | [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Selection patterns, code snippets |
403
+ | [`wizard-chrome-contract.md`](wizard-chrome-contract.md) | Copy commands, symptom → fix |
404
+ | [`agent-execution-flow.md`](agent-execution-flow.md) | Full pipeline phases |
405
+ | [`verify-agent-build.sh`](../templates/verify-agent-build.sh) | Automated gate before deploy |
@@ -1,10 +1,15 @@
1
1
  # Wizard Live Preview — Client Build Guide
2
2
 
3
3
  > **Read during Phase 5 (BUILD) — mandatory.** Wizard **run** (Phase 6b) is optional; this contract is required for every agent build.
4
+ > **Authoritative hook list + copy commands:** [`wizard-chrome-contract.md`](wizard-chrome-contract.md) — fixes logo, layout toggles, question card, and per-type preview issues.
5
+ > **Complete control catalog (all steps, types, formats):** [`wizard-customization-catalog.md`](wizard-customization-catalog.md).
4
6
  > Pipeline: [`agent-execution-flow.md`](agent-execution-flow.md).
5
7
 
6
8
  Related docs:
7
9
 
10
+ - [`wizard-customization-catalog.md`](wizard-customization-catalog.md) — **every wizard control** → config → CSS var → component
11
+ - [`wizard-chrome-contract.md`](wizard-chrome-contract.md) — **copy-first templates** + symptom → fix table
12
+
8
13
  - [`ui-customization-wizard.md`](ui-customization-wizard.md) — wizard flow and CLI
9
14
  - [`apply-ui-config.md`](apply-ui-config.md) — applying final `survey-ui-config.json` after wizard
10
15
  - [`wizard-api.md`](wizard-api.md) — EC2 `/wizard/*` API
@@ -51,14 +56,25 @@ If components use **hardcoded** colors (`bg-[#e20074]`) with no `var(--cfm-*)` h
51
56
 
52
57
  ## Required project artifacts (Phase 5)
53
58
 
54
- Create these **before** the client opens the wizard:
59
+ **Copy wizard-ready templates first** (do not hand-write chrome from `apps/client`):
60
+
61
+ | Template (SDK) | Copy to |
62
+ |----------------|---------|
63
+ | `templates/docs/templates/Header.tsx` | `src/components/Header.tsx` |
64
+ | `templates/docs/templates/Footer.tsx` | `src/components/Footer.tsx` |
65
+ | `templates/docs/templates/ProgressBar.tsx` | `src/components/ProgressBar.tsx` |
66
+ | `templates/docs/templates/SurveyStickyChrome.tsx` | `src/components/SurveyStickyChrome.tsx` |
67
+ | `templates/docs/templates/LanguageSelector.tsx` | `src/components/LanguageSelector.tsx` |
68
+ | `templates/docs/templates/PreviewBridgeInit.tsx` | `src/components/PreviewBridgeInit.tsx` |
69
+ | `templates/previewBridge.ts` | `src/lib/previewBridge.ts` |
70
+ | `templates/survey-theme.css` | `src/styles/survey-theme.css` |
71
+ | `templates/docs/templates/Question.tsx` | `src/components/Question.tsx` (dispatcher base) |
72
+
73
+ Full symptom → fix table: [`wizard-chrome-contract.md`](wizard-chrome-contract.md).
55
74
 
56
75
  | File | Purpose |
57
76
  |------|---------|
58
- | `src/styles/survey-theme.css` | All `--cfm-*` CSS custom properties (defaults from mockup) |
59
77
  | `survey-ui-config.json` (draft) | Seeds wizard form fields from agent branding |
60
- | `src/lib/previewBridge.ts` | Live bridge in **local dev** (`npx cfm-sdk customize`) — copy from `templates/previewBridge.ts` |
61
- | `src/components/PreviewBridgeInit.tsx` | Mount bridge once in `layout.tsx` (local dev only) |
62
78
 
63
79
  Import theme in `globals.css`:
64
80
 
@@ -1,6 +1,7 @@
1
1
  # Wizard Question-Type Styling
2
2
 
3
- > **Read during Phase 5 (BUILD) — mandatory.** Alongside [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) and [`apply-ui-config.md`](apply-ui-config.md).
3
+ > **Read during Phase 5 (BUILD) — mandatory.** Alongside [`wizard-customization-catalog.md`](wizard-customization-catalog.md) (complete control index), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) and [`apply-ui-config.md`](apply-ui-config.md).
4
+ > **After client saves wizard:** [`wizard-post-customize-build.md`](wizard-post-customize-build.md) — full format matrix + Phase 6c runbook.
4
5
  > Pipeline: [`agent-execution-flow.md`](agent-execution-flow.md).
5
6
 
6
7
  **Do not change** `Question.tsx` dispatch logic, answer shapes, SDK visibility helpers, or matrix routing algorithms — styling only.
@@ -75,10 +76,26 @@ Single-select radio: outer border = focus ring, annulus = cell selected, inner d
75
76
 
76
77
  ### TEXTFIELD (`TEXTFIELD_short`, `TEXTFIELD_long`)
77
78
 
78
- | Wizard section | CSS vars |
79
- |----------------|----------|
80
- | Input radius, border, placeholder | `--cfm-input-radius`, `--cfm-input-border`, `--cfm-input-placeholder` |
81
- | Focus | `--cfm-input-focus-ring` on focus outline |
79
+ | Wizard section | CSS vars | Apply in |
80
+ |----------------|----------|----------|
81
+ | Input radius, border, padding | `--cfm-input-radius`, `--cfm-input-border`, `--cfm-input-padding` | `Question.tsx` textarea |
82
+ | **Placeholder color** | `--cfm-input-placeholder` | `data-cfm-textfield` + CSS `::placeholder { color: var(--cfm-input-placeholder) }` |
83
+ | Focus | `--cfm-input-focus-ring` | focus outline |
84
+
85
+ ```tsx
86
+ <textarea
87
+ data-cfm-textfield
88
+ style={{ borderColor: 'var(--cfm-input-border)', ... }}
89
+ className="placeholder:cfm-input-ph"
90
+ />
91
+ ```
92
+
93
+ ```css
94
+ [data-cfm-textfield]::placeholder {
95
+ color: var(--cfm-input-placeholder);
96
+ opacity: 1;
97
+ }
98
+ ```
82
99
 
83
100
  ### NPS_SCALE (`NPS_SCALE`)
84
101
 
@@ -101,6 +118,8 @@ Single-select radio: outer border = focus ring, annulus = cell selected, inner d
101
118
 
102
119
  **No** per-type accent/ring overrides in CFM — use Question card tokens only.
103
120
 
121
+ **Matrix multi-row preview:** Wizard **Question Types → CFM** has a **multi-statement** toggle. Preview harness injects a second `statementRow` when enabled. `LikertMatrixScale.tsx` **must** map over `question.statementRows` — never hardcode a single row.
122
+
104
123
  ### CSAT_MATRIX (`CSAT_carousel`, `CSAT_dropdown`, `CSAT_emoji`, `CSAT_graphics`, `CSAT_numbered`, `CSAT_star`)
105
124
 
106
125
  | Format | Wizard sections | Key styling |
@@ -174,7 +193,9 @@ For production builds after wizard: syncing `survey-theme.css` is sufficient —
174
193
 
175
194
  **Wizard customization** exposes all **11** question types regardless of fetched survey inventory. Wire styling for every scale template you copy — not only types in the client's mockup image.
176
195
 
177
- For each type in **wizard export** (all 11):
196
+ **Format-level matrix** (every preview tab component): [`wizard-customization-catalog.md`](wizard-customization-catalog.md) § Question Types step.
197
+
198
+ For each type in **wizard export** (all types in `surveyTypes[]`):
178
199
 
179
200
  - [ ] Scale component uses `var(--cfm-*)` for every wizard-exposed token (no hardcoded brand hex)
180
201
  - [ ] Radio/scale selections use `selectionStyles.ts` pattern (focus ring + cell selected)
@@ -1,30 +1,28 @@
1
1
  # Survey Sticky Chrome
2
2
 
3
- > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
- > **Reference implementation:** `apps/client/src/components/SurveyStickyChrome.tsx`
3
+ > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
+ > **Wizard contract:** [`wizard-chrome-contract.md`](../00-integration/wizard-chrome-contract.md) — header and progress are **separate** toggle targets
5
5
  > **Template:** [`templates/SurveyStickyChrome.tsx`](../templates/SurveyStickyChrome.tsx)
6
- > **Component**: `SurveyStickyChrome`
7
6
 
8
7
  ## Purpose
9
8
 
10
- Wrap **Header + ProgressBar** in a single `sticky top-0` container so the progress bar stays visible when the respondent scrolls to answer questions lower on the page (especially the last question on a multi-question page).
9
+ Wrap **Header + ProgressBar** in a sticky container. The wizard toggles them **independently**:
11
10
 
12
- ## Props
11
+ | Toggle | Target |
12
+ |--------|--------|
13
+ | `showHeader` | `.cfm-header` on `<header>` only |
14
+ | `showProgressBar` | `[data-cfm-progress]` / `.cfm-progress` only |
13
15
 
14
- ```typescript
15
- type SurveyStickyChromeProps = {
16
- progressPercentage: number; // from state.progressPercentage
17
- };
18
- ```
16
+ Do **not** put class `cfm-header` on the sticky wrapper.
19
17
 
20
- ## Implementation
18
+ ## Implementation (wizard-ready)
21
19
 
22
20
  ```tsx
23
21
  export default function SurveyStickyChrome({ progressPercentage }: SurveyStickyChromeProps) {
24
22
  return (
25
- <div className="sticky top-0 z-30 bg-white shadow-[0_2px_8px_rgba(0,0,0,0.06)]">
23
+ <div className="cfm-sticky-chrome sticky top-0 z-30" style={{ background: 'var(--cfm-header-bg)' }}>
26
24
  <Header embedded />
27
- <div className="mx-auto w-full max-w-4xl px-4 pb-5 pt-4 sm:px-6 lg:px-8">
25
+ <div className="mx-auto w-full px-4" style={{ maxWidth: 'var(--cfm-max-width)' }}>
28
26
  <ProgressBar progressPercentage={progressPercentage} />
29
27
  </div>
30
28
  </div>
@@ -32,48 +30,11 @@ export default function SurveyStickyChrome({ progressPercentage }: SurveyStickyC
32
30
  }
33
31
  ```
34
32
 
35
- ## Spacing (logo progress bar)
36
-
37
- Keep a visible gap between the logo block and the progress track — do **not** flush them together.
38
-
39
- | Token | Tailwind | Purpose |
40
- |-------|----------|---------|
41
- | Top inset | `pt-4` | 16px gap below logo / header row |
42
- | Bottom inset | `pb-5` | 20px gap above scrollable question content |
43
- | Horizontal | `px-4 sm:px-6 lg:px-8` | Align track with `main` content column (`max-w-4xl`) |
44
-
45
- ## Header `embedded` prop
46
-
47
- When `Header` is inside sticky chrome, pass `embedded` to avoid a double shadow:
48
-
49
- ```tsx
50
- <header className={`relative h-[120px] w-full bg-white ${embedded ? '' : 'z-10 shadow-[0_2px_8px_rgba(0,0,0,0.06)]'}`}>
51
- ```
52
-
53
- Use the standalone `Header` (no `embedded`) on intro, end, loading, and terminal pages.
54
-
55
- ## SurveyPage wiring (content phase only)
56
-
57
- ```tsx
58
- <div className="flex min-h-screen flex-col bg-white">
59
- <SurveyStickyChrome progressPercentage={state.progressPercentage} />
60
-
61
- <main className="mx-auto w-full max-w-4xl flex-1 px-4 py-10 sm:px-6 lg:px-8">
62
- <LanguageSelector ... />
63
- {/* questions + nav */}
64
- </main>
65
-
66
- <Footer />
67
- </div>
68
- ```
69
-
70
- Do **not** render a separate `ProgressBar` inside `<main>` — it belongs in sticky chrome only.
33
+ Copy full file from [`templates/SurveyStickyChrome.tsx`](../templates/SurveyStickyChrome.tsx).
71
34
 
72
35
  ## Agent checklist
73
36
 
74
- - [ ] `SurveyStickyChrome` (or equivalent sticky wrapper) on `phase.kind === 'content'`
75
- - [ ] `ProgressBar` bound to `state.progressPercentage`
76
- - [ ] `sticky top-0 z-30 bg-white` on wrapper; single shadow on wrapper, not Header
77
- - [ ] `pt-4` gap between logo and progress track; `pb-5` below track
78
- - [ ] Progress track aligned to same `max-w-4xl` as question content
79
- - [ ] Standalone `Header` on intro / end / loading / terminal branches
37
+ - [ ] `Header.tsx` has class `cfm-header` + `data-cfm-logo` + `data-cfm-company`
38
+ - [ ] `ProgressBar.tsx` has `data-cfm-progress` + class `cfm-progress`
39
+ - [ ] Sticky wrapper uses `cfm-sticky-chrome` not `cfm-header`
40
+ - [ ] `pt`/`pb` spacing via `--cfm-sticky-pt` / `--cfm-sticky-pb`
@@ -4,7 +4,7 @@
4
4
  > **Shared lib utilities** (NPS colors, custom fields, heatmap coords) live in [`templates/`](../templates/) — see [`client-lib-folder.md`](../00-integration/client-lib-folder.md), not in this ui-specs folder.
5
5
  > Read the spec for **each question type present** in the fetched survey before writing React code.
6
6
 
7
- > **Wizard customization:** When the client may use the web wizard, hardcoded hex in § Design Tokens below are **defaults only**. Wire `var(--cfm-*)` per [`wizard-question-type-styling.md`](../00-integration/wizard-question-type-styling.md) — especially `--cfm-matrix-selected` (cell annulus) and `--cfm-input-focus-ring` (outer border + inner dot). Portable scale templates in `docs/templates/` are layout/logic baselines; extend with `selectionStyles.ts` + `labelStyles.ts` for live preview.
7
+ > **Wizard customization:** When the client may use the web wizard, hardcoded hex in § Design Tokens below are **defaults only**. Wire `var(--cfm-*)` per [`wizard-question-type-styling.md`](../00-integration/wizard-question-type-styling.md) — especially `--cfm-matrix-selected` (cell annulus) and `--cfm-input-focus-ring` (outer border + inner dot). **Full control catalog (all formats):** [`wizard-customization-catalog.md`](../00-integration/wizard-customization-catalog.md).
8
8
 
9
9
  ## How to Read a UI Spec
10
10
 
@@ -156,6 +156,10 @@
156
156
  "path": "00-integration/client-lib-folder.md",
157
157
  "purpose": "src/lib layout — customFieldValues + surveyUi portable templates"
158
158
  },
159
+ {
160
+ "path": "00-integration/wizard-chrome-contract.md",
161
+ "purpose": "Wizard DOM/CSS hook contract — copy-first Header/Footer/ProgressBar templates (Phase 5)"
162
+ },
159
163
  {
160
164
  "path": "00-integration/wizard-preview-build-guide.md",
161
165
  "purpose": "Build client components for wizard live preview — --cfm-* vars and data-cfm-* hooks (Phase 5)"
@@ -364,8 +368,10 @@
364
368
  "00-integration/agent-execution-flow.md",
365
369
  "00-integration/constraints.md",
366
370
  "00-integration/component-checklist.md",
371
+ "00-integration/wizard-customization-catalog.md",
367
372
  "00-integration/wizard-preview-build-guide.md",
368
373
  "00-integration/wizard-question-type-styling.md",
374
+ "00-integration/wizard-chrome-contract.md",
369
375
  "02-reference/routing-table.md"
370
376
  ],
371
377
  "onDemand": "02-reference/question-types"
@@ -422,6 +428,7 @@
422
428
  "read": [
423
429
  "00-integration/wizard-config-handoff.md",
424
430
  "00-integration/ui-customization-wizard.md",
431
+ "00-integration/wizard-customization-catalog.md",
425
432
  "00-integration/wizard-preview-build-guide.md",
426
433
  "00-integration/wizard-question-type-styling.md",
427
434
  "00-integration/wizard-api.md",
@@ -453,9 +460,11 @@
453
460
  "when": "wizardUsedOrSurveyUiConfigExists",
454
461
  "read": [
455
462
  "00-integration/wizard-config-handoff.md",
463
+ "00-integration/wizard-post-customize-build.md",
456
464
  "00-integration/apply-ui-config.md",
457
465
  "00-integration/wizard-preview-build-guide.md",
458
- "00-integration/wizard-question-type-styling.md"
466
+ "00-integration/wizard-question-type-styling.md",
467
+ "00-integration/wizard-chrome-contract.md"
459
468
  ],
460
469
  "inputFile": "survey-ui-config.final.json",
461
470
  "inputFileLocal": "survey-ui-config.json",