Skip to content

fix(configurator): truthful live previews, reorganized typography, usable token rows - #632

Merged
jackgranatowski merged 7 commits into
mainfrom
claude/configurator-controls-audit-zqi10q
Jul 18, 2026
Merged

fix(configurator): truthful live previews, reorganized typography, usable token rows#632
jackgranatowski merged 7 commits into
mainfrom
claude/configurator-controls-audit-zqi10q

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #631 addressing user-reported issues in the configurator: broken/lying sidebar previews, an inconsistent typography category, clipped token-value inputs, and invisible reset buttons.

  • Live var() previews everywhere. Sidebar previews computed CSS from parseNum(override) with hardcoded fallbacks, so they broke whenever a control stored a var() reference (the default for scale-backed dropdowns — e.g. Global media radius showed nothing when picking radius-xl) and showed panel guesses instead of framework defaults. The panel document already loads the framework token CSS plus live override injection, so previews now reference live tokens directly (Borders, Effects, Misc, Macros). Also fixes media radius advertising radius-m as its default when the framework default is 0.
  • Typography reorganized into sorted, complete sections: Fonts → Fluid scale → Line heights → Letter spacing → Font weights → Elements (body, h1–h6) → Line lengths. The text and display generators have identical controls (shared viewport range; each with the same base-size ClampField + modular-ratio block on the shared --sf-text-ratio-* tokens + scale multiplier), a live DOM-measured ramp (TypeSpecimenRow), and unique self-describing labels ("Text scale multiplier" vs "Display scale multiplier"). Per-size display tabs were dropped as unnecessary; no token gained or lost an editor.
  • TokenRow stacked layout — token name, description, then a full-width value control, so long clamp()/var() values are no longer clipped by the old narrow right-aligned field.
  • Reset buttons always visible when overridden — nine reset affordances used a hide-until-hover pattern (sm:opacity-0 + group-hover) and looked missing on desktop; a reset only renders when a token is overridden, so it now shows unconditionally (SliderRow's </> toggle likewise).

Type

  • fix
  • feat
  • docs
  • chore / tooling

Checklist

  • Conventional Commit messages (feat:, fix:, docs:, …) — enforced by commitlint
  • npm run lint:css passes (stylelint) — no CSS source touched (configurator-only)
  • npm run build rebuilds dist/ (bundles are git-ignored; CI rebuilds and stamps headers)
  • npm test passes (unit + Playwright e2e) — configurator suite 189/189, plus browser smoke of every changed panel
  • Version references in sync if any version-related file changed (npm run check:version) — n/a, no version files touched
  • LLM guide reviewed/updated if core/*.css, optional/*.css, or token-registry.json changed (npm run check:llm-guide) — n/a, framework untouched
  • Generated artifacts regenerated, not hand-edited (npm run check:macros, check:registry, audit:check) — n/a
  • CHANGELOG.md updated under ## [Unreleased] (for user-facing changes) — configurator-internal UI changes
  • Breaking changes include migration docs — no breaking changes

Notes

Browser-verified with Playwright against the built app: media-radius preview reacts to a var() pick (0px → 16px on radius-xl), both fluid-scale generators render identically with unique labels, the scale ramp shows real DOM-measured sizes, the full-width token editor fits a 312-char clamp() expression, and reset buttons have opacity: 1 without hovering. Two component tests updated for the relabelled reset affordance (reset).

🤖 Generated with Claude Code

https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added live typography specimen previews that reflect actual rendered font sizes.
    • Added OpenType controls for numeric figures, optical sizing, font features, and font variation.
    • Improved typography editing with clearer sections for scale, rhythm, weights, elements, and prose details.
    • Updated token controls to use stacked, full-width layouts with clearer reset actions.
  • Improvements

    • Updated visual previews to reflect configured design tokens more accurately.
    • Simplified control visibility and styling across configuration panels.

claude added 5 commits July 18, 2026 20:00
…abs incl. display

Sidebar previews computed their CSS from parseNum(override) with hardcoded
fallbacks, so they broke whenever a control stored a var() reference (the
default mode for scale-backed dropdowns) and showed panel guesses instead of
framework defaults. The panel document already loads the framework token CSS
and receives live override injection, so previews now reference the live
tokens directly and can never disagree with reality:

- Borders: media radius (also fixes its wrong "radius-m" default — the
  framework default is 0), focus ring, radius steps, border width bars,
  border sample.
- Effects: blur, opacity rows, scrollbar strip.
- Misc: touch target, focus ring.
- Macros: scrim, surface-bg composite, flow gap.

Typography — one system for text and display, as requested:
- Per-type styles now covers Body, H1–H6 AND D·S/D·M/D·L with the same tabs
  and controls; display tabs edit --sf-display-*-line-height and the shared
  --sf-font-weight-display, with Size pointing at the modular-scale controls.
- The live sample and the Scale preview render from the real tokens (var())
  with DOM-measured size labels (new TypeSpecimenRow) — no caps, no approximations.
- Display type section slims down to scale-level controls; per-size sliders
  and the duplicate Display weight grid moved into the tabs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
…ections

Drop the per-size display tabs (unnecessary) and the old scattered section
split (Body text / Font weight scale / Display type / Per-type / Modular scale
/ Scale preview / Advanced typography). All controls are re-sorted by concern
into seven complete sections:

1. Fonts — families, Google loader, OpenType axes (numeric, optical sizing,
   features, variation).
2. Fluid scale — text and display generators with IDENTICAL controls: shared
   viewport range, each with the same base-size ClampField + modular-ratio
   block (display's ratio edits the same shared --sf-text-ratio-* tokens the
   framework derives display sizes from) + scale multiplier, plus the live
   DOM-measured ramp and the Advanced power knobs.
3. Line heights — leading scale, taper, display line-heights.
4. Letter spacing — the tracking scale.
5. Font weights — the base weight scale and role weights (heading, display,
   strong, interactive) in one place, all through the shared weight grid.
6. Elements — body + h1–h6 editor (size / line height / weight / tracking /
   max width) with the live token-driven sample, plus body & prose details
   (emphasis, code size, wraps, external-link marker/label).
7. Line lengths — per-step max-widths.

No tokens gained or lost — every previously editable control is still
present, just organized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
…section

Both generators used the same "Base size & ratio" / "Scale multiplier" labels,
distinguished only by a small group header above them — ambiguous when
scanning and in ClampField's title-derived aria-labels. Labels now carry their
own context ("Text base size & ratio", "Display scale multiplier", …), and the
now-redundant Text/Display mini-headers are dropped. Verified this was the
only duplicated control label across all panels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
…dth value

The All-tokens / generic token rows squeezed the value control into a narrow
right-aligned column (w-28), clipping longer values (clamp()/var()
expressions). Restack each row vertically: token name (+ override dot, colour
swatch, reset), description, then a full-width value control — the scale
dropdown, the text editor and the value display all span the row. The reset
affordance becomes a labelled "reset" button consistent with every other
control; tests updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
…idden

Nine reset affordances (SliderRow, TokenRow, PowerKnobRow, weight grids,
tracking rows, Motion/Misc/Themes inline resets) used a hide-until-hover
pattern (sm:opacity-0 + group-hover reveal), so on desktop they were invisible
until the exact row was hovered — users reported reset "missing". A reset
button only renders when the token IS overridden, so it carries information
and should always be visible; drop the opacity dance everywhere. SliderRow's
</> raw-CSS toggle loses its hover-hide too — same discoverability problem,
same fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f25af53-6edb-4dc2-9687-f7766cc7c1dc

📥 Commits

Reviewing files that changed from the base of the PR and between 61a38c5 and d88c7f8.

📒 Files selected for processing (4)
  • configurator/src/components/DomainPanel.svelte
  • configurator/src/components/inputs/TokenRow.svelte
  • configurator/src/components/inputs/TypeSpecimenRow.svelte
  • configurator/src/components/panels/TypographyPanel.svelte
📝 Walkthrough

Walkthrough

The configurator updates typography editing, token row layout, live CSS-variable previews, and control visibility styles. A measured TypeSpecimenRow component supports token-based type previews, while related tests target the updated token reset affordance.

Changes

Configurator UI updates

Layer / File(s) Summary
Typography editor and live specimens
configurator/src/components/inputs/TypeSpecimenRow.svelte, configurator/src/components/panels/TypographyPanel.svelte
Typography sections, OpenType controls, type-level data, live samples, and body/prose controls are restructured around CSS token values and measured specimens.
Token editor layout and reset behavior
configurator/src/components/inputs/TokenRow.svelte, configurator/tests-components/token-editing.test.js
Token rows now use stacked full-width controls, conditional color swatches, and a text reset action covered by updated tests.
CSS-variable-driven panel previews
configurator/src/components/panels/{Borders,Effects,Macros,Misc}Panel.svelte
Border, effect, macro, and miscellaneous previews now read CSS custom properties with fallbacks instead of derived display values.
Persistent control affordances
configurator/src/components/inputs/{PowerKnobRow,SliderRow}.svelte, configurator/src/components/panels/{Misc,Motions,Themes}Panel.svelte
Reset, toggle, stagger, underline, and theme-delete controls no longer use opacity-based responsive or group-hover visibility classes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: codex

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: live preview fixes, typography restructuring, and improved token row usability.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/configurator-controls-audit-zqi10q

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Jul 18, 2026
@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes four user-reported configurator issues from #631: sidebar previews that broke or lied when a var() reference was stored, an inconsistent typography panel, token-value inputs that clipped long clamp() expressions, and reset buttons that were invisible on desktop until hover. All panel previews (Borders, Effects, Misc, Macros) now reference live tokens directly via var() fallbacks instead of panel-computed numbers, the typography panel is reorganised into seven sorted sections with a live DOM-measured type ramp (TypeSpecimenRow), TokenRow adopts a stacked layout for full-width value fields, and nine reset affordances drop the sm:opacity-0 group-hover pattern in favour of unconditional visibility.

  • Live previews fixed by replacing parseNum(override) fallbacks with var(--sf-*, default) in style attributes; --sf-media-radius default now correctly advertises 0 instead of radius-m.
  • Typography split into Fonts → Fluid scale → Line heights → Letter spacing → Font weights → Elements → Line lengths, with a shared viewport range, per-generator base-size/ratio controls, and a TypeSpecimenRow that uses ResizeObserver to report the true DOM-rendered size.
  • TokenRow + reset buttons — stacked layout prevents value clipping; reset renders only when overridden and is always visible when it does.

Confidence Score: 4/5

Safe to merge — all changes are confined to the configurator UI with no framework token or CSS source modifications.

The live-preview and reset-visibility fixes are mechanical and well-tested. TypographyPanel has two small gaps: the max-width token written by the new Max width input is not tracked by the tab dot indicator or the bulk-reset button, and a required tokens prop remains in the type annotation without being used — both worth tidying but neither breaks existing flows.

configurator/src/components/panels/TypographyPanel.svelte — the Elements section reset logic and tab indicator both miss the max-width token, and the unused tokens prop should be cleaned up.

Important Files Changed

Filename Overview
configurator/src/components/panels/TypographyPanel.svelte Large reorganisation into 7 sorted sections with live fluid-scale generators; two issues found: the max-width token is tracked by none of the reset/indicator paths, and a required-but-unused tokens prop is left in the type annotation.
configurator/src/components/inputs/TypeSpecimenRow.svelte New component — correctly uses ResizeObserver in a $effect with proper cleanup to DOM-measure the rendered font-size of each type scale step; no issues found.
configurator/src/components/inputs/TokenRow.svelte Redesigned to a stacked layout (name → description → full-width value control) so long clamp()/var() values are no longer clipped; reset button renders unconditionally when overridden; no issues found.
configurator/src/components/inputs/SliderRow.svelte Removed sm:opacity-0 + group-hover opacity classes from both the toggle and the reset button so both are unconditionally visible when applicable; no issues found.
configurator/src/components/inputs/PowerKnobRow.svelte Same reset-button visibility fix (removed opacity/group-hover classes); no issues found.
configurator/src/components/panels/BordersPanel.svelte Media-radius preview now uses var(--sf-media-radius, 0) directly instead of a computed value; slider fallback corrected to 0 from the old non-zero default; no issues found.
configurator/src/components/panels/EffectsPanel.svelte Sidebar previews updated to reference live var() tokens instead of panel-computed fallbacks; no issues found.
configurator/src/components/panels/MiscPanel.svelte Previews updated to reference live var() tokens; no issues found.
configurator/src/components/panels/MacrosPanel.svelte Previews updated to reference live var() tokens; no issues found.
configurator/tests-components/token-editing.test.js Tests updated to match renamed reset affordance; new assertions confirm reset button is absent when not overridden and present when overridden; coverage is appropriate.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User adjusts token control] --> B{Control type}
    B -->|SliderRow / PowerKnobRow| C[onSet / onChange fires]
    B -->|TokenRow scale picker| D[onSet fires with var ref]
    B -->|TokenRow text input| E[onBlur to onSet or onReset]
    C --> F[App stores override in overrides map]
    D --> F
    E --> F
    F --> G[Panel injects CSS override]
    G --> H[Preview element reads var token with fallback]
    H --> I{Preview type}
    I -->|TypeSpecimenRow| J[ResizeObserver measures DOM font-size]
    J --> K[Displays real rem value]
    I -->|Sidebar swatch or border or shadow| L[CSS var resolves in live document]
    L --> M[Preview reflects actual rendered output]
    F --> N{Token overridden?}
    N -->|Yes| O[Reset button visible unconditionally]
    N -->|No| P[Reset button absent]
    O --> Q[User clicks reset, override cleared]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[User adjusts token control] --> B{Control type}
    B -->|SliderRow / PowerKnobRow| C[onSet / onChange fires]
    B -->|TokenRow scale picker| D[onSet fires with var ref]
    B -->|TokenRow text input| E[onBlur to onSet or onReset]
    C --> F[App stores override in overrides map]
    D --> F
    E --> F
    F --> G[Panel injects CSS override]
    G --> H[Preview element reads var token with fallback]
    H --> I{Preview type}
    I -->|TypeSpecimenRow| J[ResizeObserver measures DOM font-size]
    J --> K[Displays real rem value]
    I -->|Sidebar swatch or border or shadow| L[CSS var resolves in live document]
    L --> M[Preview reflects actual rendered output]
    F --> N{Token overridden?}
    N -->|Yes| O[Reset button visible unconditionally]
    N -->|No| P[Reset button absent]
    O --> Q[User clicks reset, override cleared]
Loading

Comments Outside Diff (1)

  1. configurator/src/components/panels/TypographyPanel.svelte, line 16-22 (link)

    P2 Required tokens prop declared but never used

    tokens: SlashedToken[] appears as a non-optional member of the $props() type annotation but is never destructured or referenced anywhere in the component. TypeScript will therefore require every caller to provide it. If the panel now builds its type data statically (TYPE_LEVELS, TEXT_STEPS, etc. are all local constants), the prop is dead. It should either be removed from the type or marked optional (tokens?: SlashedToken[]) to avoid forcing callers to supply a value that is silently ignored.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "fix(configurator): reset buttons always ..." | Re-trigger Greptile

Comment on lines 703 to 733
@@ -488,370 +732,102 @@
>reset {activeLevel.label}</button>
{/if}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Max-width overrides invisible to reset button and tab indicator

The "Max width" input (lines 706–720) writes --sf-h*-max-width overrides, but neither the per-level tab indicator dot (line 608) nor the "reset {label}" bulk-reset button (lines 724–733) check for that token. Concretely: if a user sets only a max-width on H1, the tab dot won't appear, the reset button won't render, and even when other H1 overrides are also active and the reset button is shown, clicking it leaves --sf-h1-max-width still set.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@configurator/src/components/inputs/TokenRow.svelte`:
- Around line 64-70: Add a token-specific accessible label to the reset button
rendered by TokenRow’s isOverridden block, using the existing shortName value so
it identifies which token on the row will be reset while preserving the visible
“reset” text and onReset behavior.

In `@configurator/src/components/inputs/TypeSpecimenRow.svelte`:
- Around line 16-21: Update the rem conversion in TypeSpecimenRow.svelte to
divide by the computed font size of document.documentElement rather than the
hardcoded 16, while preserving the existing measured font-size behavior from the
$effect and measure function.

In `@configurator/src/components/panels/TypographyPanel.svelte`:
- Around line 366-397: Associate each text input in TypographyPanel, including
the “Font features,” “Variation,” “External marker,” and “External label”
inputs, with an accessible name. Use unique matching id and label for attributes
or equivalent aria-label attributes, while preserving the existing input
behavior and reset controls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ccbc7336-543e-452f-affb-41603f0d4f02

📥 Commits

Reviewing files that changed from the base of the PR and between 33555a3 and 61a38c5.

📒 Files selected for processing (12)
  • configurator/src/components/inputs/PowerKnobRow.svelte
  • configurator/src/components/inputs/SliderRow.svelte
  • configurator/src/components/inputs/TokenRow.svelte
  • configurator/src/components/inputs/TypeSpecimenRow.svelte
  • configurator/src/components/panels/BordersPanel.svelte
  • configurator/src/components/panels/EffectsPanel.svelte
  • configurator/src/components/panels/MacrosPanel.svelte
  • configurator/src/components/panels/MiscPanel.svelte
  • configurator/src/components/panels/MotionPanel.svelte
  • configurator/src/components/panels/ThemesPanel.svelte
  • configurator/src/components/panels/TypographyPanel.svelte
  • configurator/tests-components/token-editing.test.js

Comment thread configurator/src/components/inputs/TokenRow.svelte
Comment thread configurator/src/components/inputs/TypeSpecimenRow.svelte Outdated
Comment thread configurator/src/components/panels/TypographyPanel.svelte
claude added 2 commits July 18, 2026 21:28
Greptile:
- Elements section: the per-level tab dot and the "reset {label}" bulk reset
  now track --sf-h{n}-max-width alongside size/line-height/weight/tracking,
  so a max-width-only override is indicated and actually cleared.
- Drop the required-but-unused tokens prop (and its type import) from
  TypographyPanel — the panel builds its type data statically.

CodeRabbit:
- TokenRow reset gets a token-specific aria-label (`Reset {shortName}`).
- TypeSpecimenRow converts px→rem using the document root's computed
  font-size instead of a hardcoded 16.
- Every plain text input in TypographyPanel (font features, variation, Google
  font, external link marker/label, per-level and per-step max-widths) gets an
  accessible name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
The previous commit removed TypographyPanel's unused tokens prop but left the
caller passing it, which svelte-check (CI's Configurator tests gate) rejects.
Verified locally with npm run check: 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
@jackgranatowski
jackgranatowski merged commit 5607e99 into main Jul 18, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants