Skip to content

feat(configurator): unify text & display typographic scale controls - #631

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

jackgranatowski merged 9 commits into
mainfrom
claude/configurator-controls-audit-zqi10q

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

The sf-text and sf-display-text scales were edited with different inputs,
adjustments and previews despite being the same fluid clamp() scale. Make
them consistent and simpler to use:

  • Add a "Scale multiplier" slider to both scales (--sf-text-scale and
    --sf-text-display-scale) — the display multiplier was consumed by the
    preview engine but had no control; the text one likewise wasn't editable.
  • Add the missing Display S line-height; display line-heights are now s/m/l.
  • Note on the display scale that its modular ratio is shared with the text
    scale (matching the framework, which reuses --sf-text-ratio-*).
  • Give the display scale a per-step ramp preview alongside the text ramp in
    Scale preview (previously only text had one).
  • Extract a shared weight-grid snippet, removing four duplicated markup blocks.

Configurator-only; no framework tokens changed.

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

Summary by CodeRabbit

  • New Features
    • Added reusable controls for aspect-ratio presets, raw token editing, toggles, and collapsible sections.
    • Added scale-aware dropdowns for tokens with predefined variable scales.
    • Added “Copy to dark” actions for selected brand colors.
    • Added typography scale multiplier controls and improved weight selection.
  • Improvements
    • Standardized expandable sections across configuration panels.
    • Improved previews for spacing, sizing, motion, typography, and aspect ratios.
    • Simplified editing for colors, gradients, shadows, and surface settings.

claude added 8 commits July 18, 2026 14:41
The sf-text and sf-display-text scales were edited with different inputs,
adjustments and previews despite being the same fluid clamp() scale. Make
them consistent and simpler to use:

- Add a "Scale multiplier" slider to both scales (--sf-text-scale and
  --sf-text-display-scale) — the display multiplier was consumed by the
  preview engine but had no control; the text one likewise wasn't editable.
- Add the missing Display S line-height; display line-heights are now s/m/l.
- Note on the display scale that its modular ratio is shared with the text
  scale (matching the framework, which reuses --sf-text-ratio-*).
- Give the display scale a per-step ramp preview alongside the text ramp in
  Scale preview (previously only text had one).
- Extract a shared weight-grid snippet, removing four duplicated markup blocks.

Configurator-only; no framework tokens changed.

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

- Colors: add a "Copy to dark" action to the brand sources (primary,
  secondary, tertiary, action). It snapshots the light source's oklch value
  into the dark source and switches the row to manual — same effect as
  pasting the same colour into both. Not live-linked. Base/neutral/status
  are unchanged.
- Colors: replace the lone raw <input type=range> gradient-angle control with
  RangeWithNumber, matching every other angle/hue control.
- Macros: route the scrim, prose-marker and surface-bg colour fields through
  ColorInput (swatch + native picker) instead of plain text inputs.
- Effects: remove the duplicated Scrim and Scroll-shadow sections — both edit
  .sf-scrim / .sf-scroll-shadow macro tokens whose richer editors (with
  previews and text-shadow) already live in the Macros panel.

Configurator-only; no framework tokens changed.

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

Extract three reusable inputs to remove duplicated markup and unify controls
that did the same thing differently across panels:

- Toggle: the pill switch, previously hand-rolled in Shadows (glow), Motion
  (disable motion) and Misc (state flags). Two sizes.
- AspectRatioInput: one preset grid for "pick a raw aspect ratio", used by
  Macros --sf-aspect (with preview) and Layout --sf-frame-ratio.
- RawTokenRow: the "free-text token value + inline reset" row, used by Layout
  named ratios, Macros scrim text-shadow and the surface-bg image/overlay/
  animation fields.

Also give the Misc z-index tokens real per-step sliders (seeded from the
framework defaults) instead of a read-only list that punted to the All-tokens
tab, matching how every other numeric ladder is edited. Drops the phantom
--sf-z-popover entry (no such framework token).

Configurator-only; no framework tokens changed.

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

Every panel hand-copied the same button[aria-expanded] + chevron + {#if}
header block (~65 instances). Replace them with a single <Section> component
(bindable `open`, optional `variant="advanced"` and `spacing`), so section
headers are guaranteed consistent and defined once.

Rendered output is unchanged — verified across all 11 panels (sections expand/
collapse, zero runtime errors). Nested sub-section toggles that use <div>
wrappers are left as-is.

Configurator-only; no framework tokens changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
The solid/dashed/dotted line-style enum was a button-grid in Borders and Misc
but a <select> in Layout's equal-column rule. Switch it to the same button
grid so the same enum is edited the same way everywhere.

Configurator-only; no framework tokens changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
The scale-preview "Aa" ramp clamped every step to 2.5rem, so all three display
sizes (2.70/3.49/4.50rem) rendered identically. Render each step at its real
midpoint rem size instead; the box scrolls if the largest steps are tall.

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

Several sidebar mini-previews scaled a value by a constant then clamped to a
fixed pixel cap. Once several values in a set exceeded the cap they all rendered
at the same width — different sizes looking identical (the same defect as the
typography scale preview). Normalise each bar set against its own largest value
so the biggest bar fills the track and every other stays proportional and
distinct: spacing scale bars, motion duration bars, stagger delay bars, and the
Misc component-size scale. (Absolute dimensions remain in the main preview pane.)

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

Panel controls already default to the scale dropdown (via SliderRow's
variableOptions), but scale-referencing tokens without a dedicated control —
editable only in the All-tokens / generic list — fell back to a plain text box,
presenting a raw value instead of the variable.

Add scaleForValue() to map a token's default (e.g. var(--sf-space-m)) to its
sibling scale, and teach TokenRow to render that scale as a dropdown by default,
with the raw text box behind "Custom…". Only a pure single-token reference
qualifies, so compound values (e.g. a border shorthand) keep the text editor.

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: 10 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: 0873b917-1208-45e7-b6af-b6701d63b8ea

📥 Commits

Reviewing files that changed from the base of the PR and between fa2cff9 and d6b3724.

📒 Files selected for processing (3)
  • configurator/src/components/panels/ColorsPanel.svelte
  • configurator/src/components/panels/MotionPanel.svelte
  • configurator/src/components/panels/TypographyPanel.svelte
📝 Walkthrough

Walkthrough

Adds reusable Svelte controls for sections, toggles, aspect ratios, and raw tokens. Refactors configurator panels to use them, adds scale-aware token selection, and updates color, typography, motion, spacing, and preview controls.

Changes

Shared configurator controls

Layer / File(s) Summary
Shared inputs and scale-backed token selection
configurator/src/components/inputs/*, configurator/src/components/inputs/TokenRow.svelte, configurator/src/lib/variableScales.ts
Adds reusable controls and scale detection for preset, raw-token, toggle, collapsible-section, and variable-backed token editing.

Panel integrations

Layer / File(s) Summary
Accordion migration across core panels
configurator/src/components/panels/{Borders,Colors,Components,Effects}Panel.svelte
Replaces inline collapsible markup with Section and updates brand-color, gradient, and effect controls.
Layout and macro editor integration
configurator/src/components/panels/{Layout,Macros}Panel.svelte
Uses shared sections and inputs for layout ratios, rule styles, raw tokens, colors, and macro controls.
Remaining panel updates
configurator/src/components/panels/{Misc,Motion,Shadows,Spacing}Panel.svelte
Adds shared sections and toggles, updates token lists, and recalculates several visual previews.
Typography controls and previews
configurator/src/components/panels/TypographyPanel.svelte
Centralizes weight grids, adds scale multipliers, updates collapsible sections, and revises typography previews.

Estimated code review effort: 4 (Complex) | ~60 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 matches the main typography change: unifying text and display scale controls in the configurator.
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 unifies the text and display typographic scale controls in the configurator, making both scales expose the same set of adjustments and previews. It also ships a broad refactoring of shared UI patterns across all panels.

  • Scale parity: adds a "Scale multiplier" slider to both the text scale (--sf-text-scale) and display scale (--sf-text-display-scale) sections; adds the previously-missing Display S line-height control (the token existed in core/tokens.css with default var(--sf-leading-tight)); expands the Scale Preview to show a per-step display ramp alongside the text ramp, now with uncapped sizes inside a scrollable container.
  • New shared input components: Section replaces ~50 duplicated collapsible <section>+<button>+{#if} blocks across every panel; Toggle, AspectRatioInput, and RawTokenRow eliminate additional hand-rolled patterns in Macros, Layout, and Effects panels.
  • Other improvements: scaleForValue() enables a scale-picker dropdown in TokenRow for tokens whose default is a single var(--sf-*-*) reference; the MiscPanel z-index section gains per-layer SliderRow controls with default values that match core/tokens.css; ColorsPanel gains a "Copy to dark" snapshot button; --sf-z-popover (which has no matching framework token) is correctly removed.

Confidence Score: 5/5

All changes are confined to the configurator UI; no framework tokens or CSS bundles are modified.

The feature additions are straightforward and the token defaults used in the configurator (e.g. def: 1.1 for --sf-display-s-line-height) have been verified to match the live framework values in core/tokens.css. The widespread Section refactor is mechanical and low-risk. The one behavioral nuance — the weightGrid snippet now calls onReset when clicking an already-default weight with no override — is benign in practice but worth a second look if onReset acquires side effects.

The weightGrid snippet in TypographyPanel.svelte is the only place that changed observable behavior; all other files are structural refactors or additive features.

Important Files Changed

Filename Overview
configurator/src/components/panels/TypographyPanel.svelte Core feature work: adds display-scale multiplier slider, Display S line-height control, display per-step scale preview, and extracts duplicate weight-grid markup into a shared snippet. Token defaults and scale factors align with the framework CSS.
configurator/src/lib/variableScales.ts Adds scaleForValue() utility that maps a token's default var(--sf--) reference to its parent VarOption[] scale, enabling the new scale-picker dropdown in TokenRow. Logic is correct; the pure single-var-ref guard prevents clobbering compound values.
configurator/src/components/inputs/Section.svelte New shared collapsible section component replacing ~50 duplicated button+{#if} patterns across all panels. Uses $bindable for open state, supports default/advanced variants, and correctly propagates aria-expanded.
configurator/src/components/inputs/Toggle.svelte New shared toggle component extracted from three panels. sm and md sizes both have correct translate/track ratios. aria-pressed is set correctly.
configurator/src/components/inputs/AspectRatioInput.svelte New shared preset-grid component for aspect-ratio tokens. Clicking the default preset resets rather than sets, optional preview box included. Normalises whitespace in value comparisons correctly.
configurator/src/components/inputs/RawTokenRow.svelte New shared labelled text-input for arbitrary CSS token values. Empty (post-trim) input resets the override; raw value stored verbatim as documented.
configurator/src/components/inputs/TokenRow.svelte Gains a scale-picker dropdown when a token's default value is a single known var() reference; falls through to expanded text input via Custom. Logic for showing/hiding the picker is correct.
configurator/src/components/panels/MiscPanel.svelte Z-index section upgraded from a read-only list to per-layer SliderRow controls with correct default values aligned to core/tokens.css. Removes the non-existent --sf-z-popover token and reorders layers to match ascending z-value order.
configurator/src/components/panels/EffectsPanel.svelte Removes Scrim overlay and Scroll shadow sections (moved to MacrosPanel); replaces inline section patterns with Section component. Scroll shadow feature is preserved and consolidated in MacrosPanel.
configurator/src/components/panels/ColorsPanel.svelte Adds Copy to dark button for primary/secondary/tertiary/action brand sources that snapshots the light OKLCH value into the dark source. Section component refactor applied throughout.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User adjusts typography control] --> B{Which scale?}
    B -->|Text scale slider| C[Modular Scale section]
    B -->|Display scale slider| D[Display Type section]
    B -->|Display S line-height| E[Display line-height grid 3-col]
    B -->|Weight button grid| F{weightGrid snippet}
    C --> G[Scale Preview Text ramp]
    D --> H[Scale Preview Display ramp]
    F --> I{clicked weight == default?}
    I -->|Yes + override exists| J[onReset]
    I -->|No| K[onSet]
    G --> L[max-h-96 scrollable container]
    H --> L
    M[scaleForValue] --> N{pure var ref?}
    N -->|Yes| O[VarOption array]
    N -->|No| P[null]
    O --> Q[TokenRow dropdown]
    P --> Q
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 typography control] --> B{Which scale?}
    B -->|Text scale slider| C[Modular Scale section]
    B -->|Display scale slider| D[Display Type section]
    B -->|Display S line-height| E[Display line-height grid 3-col]
    B -->|Weight button grid| F{weightGrid snippet}
    C --> G[Scale Preview Text ramp]
    D --> H[Scale Preview Display ramp]
    F --> I{clicked weight == default?}
    I -->|Yes + override exists| J[onReset]
    I -->|No| K[onSet]
    G --> L[max-h-96 scrollable container]
    H --> L
    M[scaleForValue] --> N{pure var ref?}
    N -->|Yes| O[VarOption array]
    N -->|No| P[null]
    O --> Q[TokenRow dropdown]
    P --> Q
Loading

Reviews (1): Last reviewed commit: "feat(configurator): variable-first dropd..." | Re-trigger Greptile

<div class="flex gap-1">
{#each WEIGHT_OPTIONS as w (w)}
<button
onclick={() => w === defaultVal ? onReset(tokenName) : onSet(tokenName, w)}

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 The new weightGrid snippet simplifies the onclick handler compared to the original inline versions, but drops a deliberate no-op guard. The original handler did nothing when you clicked the already-selected default weight with no override (w === defaultVal && !isOverridden ? undefined); the snippet now always calls onReset(tokenName) in that case. If onReset has any side effects beyond removing the CSS override (e.g. marking a token as "dirty", triggering export diffing), clicking the default button on a fresh/unmodified state would now fire that path unnecessarily.

Suggested change
onclick={() => w === defaultVal ? onReset(tokenName) : onSet(tokenName, w)}
onclick={() => w === defaultVal ? (tokenName in overrides ? onReset(tokenName) : undefined) : onSet(tokenName, w)}

@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: 2

🧹 Nitpick comments (1)
configurator/src/components/inputs/Section.svelte (1)

21-27: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add type="button" to shared button controls.

Several new shared input components omit type="button" on their <button> elements. By default, buttons act as submit buttons. While this doesn't break anything in the current client-only architecture if they aren't wrapped in a <form>, it's a best practice to explicitly set type="button" on interactive UI toggles and resets to prevent unexpected form submissions in the future.

  • configurator/src/components/inputs/Section.svelte#L21-L27: add type="button" to the accordion toggle button.
  • configurator/src/components/inputs/AspectRatioInput.svelte#L31-L38: add type="button" to the preset option button.
  • configurator/src/components/inputs/RawTokenRow.svelte#L31-L33: add type="button" to the reset button.
🤖 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/inputs/Section.svelte` around lines 21 - 27, Add
type="button" to the interactive button elements in Section.svelte (accordion
toggle), AspectRatioInput.svelte (preset option), and RawTokenRow.svelte (reset
control), preserving their existing handlers and behavior.
🤖 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/panels/ColorsPanel.svelte`:
- Around line 435-441: Update copyLightToDark so it resolves the light source to
its current concrete color value before passing it to onSet, rather than storing
the potentially dynamic result of sourceValue(light). Preserve the autoDarkSet
removal and ensure the stored dark value is a one-shot snapshot unaffected by
later light-source changes.

In `@configurator/src/components/panels/MotionPanel.svelte`:
- Line 278: Update the stagger bar width in the MotionPanel markup to normalize
each bar’s delayMs against a maxStaggerDelay, replacing the fixed n / 5
calculation. Compute maxStaggerDelay from the same effective token values used
when deriving each delayMs, matching the duration preview’s normalization
behavior.

---

Nitpick comments:
In `@configurator/src/components/inputs/Section.svelte`:
- Around line 21-27: Add type="button" to the interactive button elements in
Section.svelte (accordion toggle), AspectRatioInput.svelte (preset option), and
RawTokenRow.svelte (reset control), preserving their existing handlers and
behavior.
🪄 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: 82502df6-d214-452c-87cc-e57f92b113c5

📥 Commits

Reviewing files that changed from the base of the PR and between 7244deb and fa2cff9.

📒 Files selected for processing (17)
  • configurator/src/components/inputs/AspectRatioInput.svelte
  • configurator/src/components/inputs/RawTokenRow.svelte
  • configurator/src/components/inputs/Section.svelte
  • configurator/src/components/inputs/Toggle.svelte
  • configurator/src/components/inputs/TokenRow.svelte
  • configurator/src/components/panels/BordersPanel.svelte
  • configurator/src/components/panels/ColorsPanel.svelte
  • configurator/src/components/panels/ComponentsPanel.svelte
  • configurator/src/components/panels/EffectsPanel.svelte
  • configurator/src/components/panels/LayoutPanel.svelte
  • configurator/src/components/panels/MacrosPanel.svelte
  • configurator/src/components/panels/MiscPanel.svelte
  • configurator/src/components/panels/MotionPanel.svelte
  • configurator/src/components/panels/ShadowsPanel.svelte
  • configurator/src/components/panels/SpacingPanel.svelte
  • configurator/src/components/panels/TypographyPanel.svelte
  • configurator/src/lib/variableScales.ts

Comment thread configurator/src/components/panels/ColorsPanel.svelte Outdated
Comment thread configurator/src/components/panels/MotionPanel.svelte Outdated
- weightGrid: restore the no-op guard so clicking the already-selected default
  weight on an unmodified token no longer calls onReset unnecessarily.
- copyLightToDark: freeze a concrete snapshot — copy a plain oklch/hex/rgb
  literal as-is (keeps OKLCH authoring), but resolve a var()-referencing light
  value so the copied dark value can't keep tracking its dependency.
- stagger preview: size the delay bars by delayMs / max stagger delay, matching
  the duration preview's normalisation instead of a fixed n/5 staircase.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
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