feat(configurator): preview hub redesign — domain-synced previews + foldable generators - #399
feat(configurator): preview hub redesign — domain-synced previews + foldable generators#399jackgranatowski wants to merge 6 commits into
Conversation
…oldable generators Phase 1 — Foldable ScaleGenerator: - Add `collapsible` prop to ScaleGenerator; when true, starts collapsed and renders a chevron toggle button in the header. - DomainPanel passes `collapsible` to every ScaleGenerator instance. Phase 2 — Preview Hub with domain auto-sync: - Preview pane SECTIONS expanded from 7 → 13 tabs, one per framework domain: Overview · Colors · Gradients · Palette · Type · Spacing · Layout · Borders · Shadows · Motion · Effects · Macros · Tokens - $effect in Preview.svelte syncs activeSection to ui.domain on every domain-tab switch; users can still manually override the preview tab. Phase 3 — New preview sections with live token feedback: - Gradients: brand + directional fades + gradient-on-content hero card. - Spacing: full 2xs–3xl ruler, gap demos, section-pad demo. - Borders: radius ramp on real cards, border-color variants, focus-ring trio. - Shadows: elevation ramp, shadow on real cards, text/drop/glow/inner examples. - Motion: animation demos, duration sweep bars, easing sweep bars. - Effects: blur scale, opacity scale, scrim/overlay demo, frosted-glass panel. DX: inline DomainPreview cards removed — previews live exclusively in the right Preview Hub, which auto-syncs. Left panel is now purely editing controls. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
…rt section defaults - Add HeadingEditor.svelte: ACSS-style tabbed editor (All/H1-H6/Body/Mono) with live specimen preview and per-level token rows; replaces flat basicGroups for the Typography domain in DomainPanel - Add foldState.js: lightweight localStorage persistence for open/closed state keyed by section ID; survives page reloads without touching the Svelte store - Wire foldState into SmartSettings: sections default to closed and remember their state per domain (key: `domainId:sectionId`) - Wire foldState into ScaleGenerator: collapsed state persists across page loads (key: `generator:type/display/space`) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
… width bars - BrandColorRow: add 7-step inline shade strip below each brand color row, resolved live against the active preview theme using the probe host - RadiusEditor.svelte: ACSS-style tabbed radius editor (All + 2xs→full tabs) with a proportional shape specimen per level and a mini-map row for quick navigation; wired into the Borders domain in DomainPanel - ContainerBars.svelte: proportional bar chart for all --sf-container-* tokens showing relative widths with live px estimates; wired into the Layout domain in DomainPanel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
- foldState: guard localStorage parse result against non-object types - ScaleGenerator: remove redundant collapsible guard in toggle handler - HeadingEditor: include all token groups in 'all' tab override detection - RadiusEditor: include per-level tokens in 'all' tab override detection - ContainerBars: use 0 fallback pct for unmeasurable widths (not 100) - ContainerBars: remove unused imports from earlier Qodo cleanup - Preview: remove hardcoded duplicate full-radius item - BrandColorRow: remove unused perceived() helper and parseRgb import Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
…-specific overrides Replaces broad `for (const k in overrides)` dependency with targeted reads of only the two source tokens for this row, avoiding redundant measureBackground reflows on every unrelated override change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DfCd6Mb2ocTxPFXYjeKg4F
📝 WalkthroughWalkthroughThe PR adds a localStorage-backed fold state utility and wires collapsible behavior into ChangesConfigurator UI Expansion
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoConfigurator preview hub redesign with domain-synced tabs and foldable generators Description
Diagram
High-Level Assessment
Files changed (9)
|
There was a problem hiding this comment.
🧹 Nitpick comments (2)
configurator/src/components/RadiusEditor.svelte (1)
99-107: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winMini previews are keyboard-inaccessible and will trigger Svelte a11y warnings.
.rad__miniis a non-interactive<div>with anonclickbut norole,tabindex, or key handler. Keyboard users can't switch levels via the mini strip, and Svelte 5 emitsa11y_click_events_have_key_events/a11y_no_static_element_interactions. Use a<button>so it's focusable and operable for free.♿ Proposed fix: render mini previews as buttons
{`#each` LEVELS.filter((l) => exists(l.token)) as l (l.id)} {`@const` [sw, sh] = DEMO_SIZES[l.id]} - <div + <button + type="button" class="rad__mini" class:rad__mini--active={l.id === activeTab} onclick={() => (activeTab = l.id)} title={l.token} + aria-label="{l.label} radius" style:width="{Math.min(sw, 44)}px" style:height="{Math.min(sh, 44)}px" style:border-radius="var({l.token})" - ></div> + ></button> {/each}Add
border: none; padding: 0;to the.rad__minirule to keep the existing appearance.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@configurator/src/components/RadiusEditor.svelte` around lines 99 - 107, The mini preview element in RadiusEditor.svelte is a non-interactive div using onclick, which causes Svelte a11y warnings and blocks keyboard access. Update the mini preview markup in the RadiusEditor component to use a button for each tab/level so it is focusable and operable by keyboard, keeping the existing active-state behavior tied to activeTab and l.id. Preserve the current visual styling by adjusting the .rad__mini styles as needed (for example to remove default button chrome) so the appearance stays the same while eliminating the accessibility issue.configurator/src/components/DomainPanel.svelte (1)
5-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueStale module doc comment. This block still describes Zone 1 as a "LIVE PREVIEW (always visible, leads the panel)" with a "DomainPreview card at top", but the preview now lives in the right-side Preview Hub and Zone 1 is controls-only (per line 230). Updating avoids misleading future readers.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@configurator/src/components/DomainPanel.svelte` around lines 5 - 23, Update the stale module doc comment in DomainPanel.svelte so it matches the current three-zone layout: Zone 1 is controls-only, and the live preview now lives in the right-side Preview Hub rather than a top-aligned DomainPreview card. Adjust the descriptive text around the layout principle and the LIVE PREVIEW/QUICK CONTROLS sections to reflect the actual structure used by DomainPanel and its generator domain flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@configurator/src/components/DomainPanel.svelte`:
- Around line 5-23: Update the stale module doc comment in DomainPanel.svelte so
it matches the current three-zone layout: Zone 1 is controls-only, and the live
preview now lives in the right-side Preview Hub rather than a top-aligned
DomainPreview card. Adjust the descriptive text around the layout principle and
the LIVE PREVIEW/QUICK CONTROLS sections to reflect the actual structure used by
DomainPanel and its generator domain flow.
In `@configurator/src/components/RadiusEditor.svelte`:
- Around line 99-107: The mini preview element in RadiusEditor.svelte is a
non-interactive div using onclick, which causes Svelte a11y warnings and blocks
keyboard access. Update the mini preview markup in the RadiusEditor component to
use a button for each tab/level so it is focusable and operable by keyboard,
keeping the existing active-state behavior tied to activeTab and l.id. Preserve
the current visual styling by adjusting the .rad__mini styles as needed (for
example to remove default button chrome) so the appearance stays the same while
eliminating the accessibility issue.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 85dec244-d847-4c13-ab3a-9c6f76fe4e54
📒 Files selected for processing (9)
configurator/src/components/BrandColorRow.svelteconfigurator/src/components/ContainerBars.svelteconfigurator/src/components/DomainPanel.svelteconfigurator/src/components/HeadingEditor.svelteconfigurator/src/components/Preview.svelteconfigurator/src/components/RadiusEditor.svelteconfigurator/src/components/ScaleGenerator.svelteconfigurator/src/components/SmartSettings.svelteconfigurator/src/lib/foldState.js
Code Review by Qodo
Context used✅ Compliance rules (platform):
5 rules 1. Preview sync incomplete
|
| const DOMAIN_TO_SECTION = { | ||
| home: 'overview', | ||
| colors: 'colors', | ||
| gradients: 'gradients', | ||
| typography: 'typography', | ||
| spacing: 'spacing', | ||
| layout: 'layout', | ||
| borders: 'borders', | ||
| shadows: 'shadows', | ||
| motion: 'motion', | ||
| effects: 'effects', | ||
| misc: 'tokens', | ||
| }; | ||
|
|
||
| let activeSection = $state('overview'); | ||
|
|
||
| $effect(() => { | ||
| const sec = DOMAIN_TO_SECTION[ui.domain]; | ||
| if (sec) activeSection = sec; | ||
| }); | ||
|
|
There was a problem hiding this comment.
2. Preview sync incomplete 🐞 Bug ≡ Correctness
Preview.svelte always starts activeSection as 'overview' and only later syncs it in an $effect, so reloads with a persisted non-home ui.domain initially render the wrong preview tab; additionally, tool domains (wcag/themes/setup/cheatsheet) are valid ui.domain values but have no mapping, so switching to them leaves the preview stuck on the previously active section.
Agent Prompt
### Issue description
The new domain→section sync logic in `Preview.svelte` has two functional gaps:
1) `activeSection` is initialized to `'overview'` regardless of the persisted `ui.domain`, then corrected later in an `$effect`, so initial render can show the wrong preview section.
2) `DOMAIN_TO_SECTION` has no entries for tool domains that are valid `ui.domain` values (`wcag`, `themes`, `setup`, `cheatsheet`), so the `$effect` becomes a no-op for those domain switches and the preview remains on the previous section.
### Issue Context
`ui.domain` is persisted/restored (store initializes it from saved UI state), and the domain taxonomy includes tool-only domains.
### Fix Focus Areas
- configurator/src/components/Preview.svelte[46-82]
### Suggested fix direction
- Initialize `activeSection` from `ui.domain` synchronously, e.g. `let activeSection = $state(DOMAIN_TO_SECTION[ui.domain] ?? 'overview');`.
- Add explicit mapping behavior for tool domains. If the intended behavior is “tools show Overview”, map them to `'overview'`; otherwise handle them explicitly (e.g. keep the last section intentionally) but then remove/adjust the unconditional sync effect so behavior is deterministic and matches the feature description.
- Keep manual override behavior by continuing to set `activeSection` directly on preview tab button clicks.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
Phase 1 — Foldable ScaleGenerator:
collapsibleprop to ScaleGenerator; when true, starts collapsed andrenders a chevron toggle button in the header.
collapsibleto every ScaleGenerator instance.Phase 2 — Preview Hub with domain auto-sync:
Overview · Colors · Gradients · Palette · Type · Spacing · Layout ·
Borders · Shadows · Motion · Effects · Macros · Tokens
domain-tab switch; users can still manually override the preview tab.
Phase 3 — New preview sections with live token feedback:
DX: inline DomainPreview cards removed — previews live exclusively in the
right Preview Hub, which auto-syncs. Left panel is now purely editing controls.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Epa7UcqpdP8E7mcG9nHLWH
Summary by CodeRabbit
New Features
Improvements