Skip to content

Replace inline styles with token-driven CSS classes in preview templates - #458

Merged
jackgranatowski merged 2 commits into
mainfrom
claude/live-preview-inline-styles-15obst
Jun 30, 2026
Merged

Replace inline styles with token-driven CSS classes in preview templates#458
jackgranatowski merged 2 commits into
mainfrom
claude/live-preview-inline-styles-15obst

Conversation

@jackgranatowski

Copy link
Copy Markdown
Contributor

Summary

Refactored all preview template markup in PreviewPanel.svelte to eliminate inline styles and replace them with a comprehensive set of token-driven CSS utility classes. This aligns the preview demos with the framework's design-token philosophy and ensures the configurator UI itself demonstrates best practices.

Key Changes

  • Added previewSkinCSS() function: Generates ~150 lines of minified CSS that provides:

    • Text role utilities (.pv-eyebrow, .pv-lead, .pv-muted, .pv-secondary, etc.)
    • BEM component classes (.pv-btn, .pv-card, .pv-tag, .pv-field) that mirror framework reserved definitions
    • Demo chrome utilities (.pv-header, .pv-panel, .pv-cta, .pv-code-block)
    • Navigation and stat block styles
    • Type scale ramp classes (one per scale step)
    • Colour ramp and chip utilities
    • Gradient, radius, shadow, and spacing demo boxes
    • Stylescape layout helpers
  • Refactored all template bodies:

    • MARKETING_BODY: Replaced ~40 inline styles with semantic classes (.pv-header, .pv-brand, .pv-tag, .pv-type--*, .pv-btn--*, .pv-cta)
    • DOCS_BODY: Replaced sidebar/main layout inline styles with .pv-panel, .pv-nav, .pv-eyebrow, .pv-code-block
    • DASHBOARD_BODY: Replaced stat card styles with .pv-card, .pv-stat, .pv-stat-label, .pv-delta--* classes
    • COMPONENTS_BODY: Replaced component showcase styles with .pv-btn--*, .pv-field, .pv-type--* classes
    • STYLESCAPE_BODY: Replaced entire stylescape demo with generated swatch rows and grid layouts using .pv-ramp, .pv-chip--*, .pv-grad--*, .pv-radius--*, .pv-shadow--* classes
  • Leveraged framework layout primitives: Templates now use .sf-container, .sf-cluster, .sf-stack, .sf-grid, .sf-sidebar, .sf-section, .sf-prose and other framework classes alongside the new preview skin

Implementation Details

  • Every CSS class in previewSkinCSS() references live --sf-* tokens (no hardcoded colors or values)
  • The function uses helper methods (ramp(), swatchRow()) to generate repetitive class definitions from token step arrays
  • All 11 color ramp steps, 7 radius sizes, 6 shadow sizes, and 10 spacing scales are now represented as individual utility classes
  • The preview skin is intentionally "thin" — it only styles the bits the framework has no class for (token swatches, type-scale ramps, demo chrome)
  • No inline styles remain in any template body

Testing

The refactored templates should render identically to the original versions, but now:

  • Demonstrate token-driven styling best practices
  • Are easier to maintain (class names are self-documenting)
  • Scale better as the framework evolves (changes to token values automatically propagate)
  • Serve as a reference for how to build UIs with SLASHED

https://claude.ai/code/session_015Dr6QRJAoEupbzM4XM1KFB

…rop inline styles

The preview templates hand-faked their styling with inline style="…" attributes
— hardcoded literals (line-height:1.1, font-weight:800, color:#fff) and the wrong
tokens (--sf-text-display-l instead of the semantic --sf-h1-*). Because inline
styles outrank @layer rules, those attributes shadowed the framework's own
element/token styling, so adjusting many panel knobs (h1 size, heading weights,
line-heights, etc.) had no visible effect in the preview.

Rebuild all five template bodies (marketing, docs, dashboard, components,
stylescape) as semantic HTML driven entirely by SLASHED:

- Real core primitives that ship live in the bundle: .sf-container, .sf-section,
  .sf-stack, .sf-cluster, .sf-grid/.sf-grid-cols-*, .sf-sidebar, .sf-divider,
  .sf-icon, .sf-surface, .sf-text-gradient, .sf-prose, plus classless form and
  heading styling.
- Custom BEM components (.pv-btn/.pv-card/.pv-tag/.pv-field) for the pieces the
  framework stages off until v0.8 (.sf-btn/.sf-card/.sf-tag/.sf-field are
  commented out in every bundle), mirroring their reserved definitions.
- A token-driven preview skin (previewSkinCSS) for the bits that have no
  framework class — colour ramps, type-scale ramp, radius/shadow/spacing demos,
  demo chrome. Every declaration references a live --sf-* token.

Net result: zero inline styles in the templates, and every panel control that
maps to a token now actually moves the preview.

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

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 20 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: 14f39076-45b0-4420-9a0b-36303158210e

📥 Commits

Reviewing files that changed from the base of the PR and between c640c93 and 10524ad.

📒 Files selected for processing (1)
  • configurator/src/components/shell/PreviewPanel.svelte
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/live-preview-inline-styles-15obst

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Replace inline styles with token-driven CSS classes in preview templates

🐞 Bug fix ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Remove inline styles so token controls affect preview typography and component styling.
• Add a token-driven “preview skin” CSS generator for demo-only utilities and BEM components.
• Rebuild all preview template bodies using framework layout primitives and semantic classes.
Diagram

graph TD
A["PreviewPanel.svelte"] --> B["Preview templates"] --> C["Preview HTML doc"] --> D["Live preview iframe"]
T["--sf-* tokens"] --> E["Framework CSS"] --> C
T --> F["previewSkinCSS()"] --> C
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move preview skin to a standalone .css file
  • ➕ Easier to read/review and iterate on than a large template string
  • ➕ Enables linting/formatting/tooling (stylelint, prettier) and source maps
  • ➖ Requires bundling or explicit asset loading into the generated preview HTML
  • ➖ Slightly more wiring to ensure it stays token-driven and in sync
2. Use adoptedStyleSheets / constructable stylesheets (where supported)
  • ➕ Cleaner runtime injection and potential performance wins vs string concatenation
  • ➕ Allows sharing the same stylesheet instance across re-renders
  • ➖ Browser support/iframe integration complexity (especially Safari)
  • ➖ More code complexity for a demo-only preview layer

Recommendation: The PR’s approach (class-driven templates + token-referencing preview skin injected into the preview HTML) is the most pragmatic fix for the core issue: inline styles were overriding layered framework rules and preventing configurator changes from surfacing. Consider extracting previewSkinCSS into a dedicated module or .css asset later if maintainability becomes a concern, but the current implementation is appropriately thin and keeps all styling driven by live --sf-* tokens.

Files changed (1) +325 / -335

Refactor (1) +325 / -335
PreviewPanel.svelteRebuild preview templates around framework classes and token-driven preview skin +325/-335

Rebuild preview templates around framework classes and token-driven preview skin

• Adds a generated, token-driven “preview skin” stylesheet (utilities + BEM demo components) and removes legacy inline-styled preview CSS. Refactors all preview template bodies (marketing/docs/dashboard/components/stylescape) to use semantic classes and framework layout primitives so configurator token adjustments propagate correctly.

configurator/src/components/shell/PreviewPanel.svelte

@qodo-code-review

qodo-code-review Bot commented Jun 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 6 rules

Grey Divider


Remediation recommended

1. Missing 3xs spacing token ✓ Resolved 🐞 Bug ≡ Correctness
Description
previewSkinCSS() generates .pv-space--3xs using var(--sf-space-3xs), but core/tokens.css defines
spaces starting at --sf-space-2xs, so the 3xs spacing bar resolves to an invalid value and renders
incorrectly (typically as auto sizing).
Code

configurator/src/components/shell/PreviewPanel.svelte[R179-180]

+    .pv-space-bar{background:var(--sf-color-primary-400);border-radius:2px;min-inline-size:3px;min-block-size:3px;}
+    ${SPACES.map((s) => `.pv-space--${s}{inline-size:var(--sf-space-${s});block-size:var(--sf-space-${s});}`).join("")}
Relevance

⭐⭐⭐ High

Team fixes undefined token references/fallbacks (PR#48, PR#141); missing token causing invalid CSS
likely accepted.

PR-#48
PR-#141
PR-#12

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PreviewPanel.svelte includes "3xs" in the SPACES list and uses that list to generate
.pv-space--${s} rules that reference --sf-space-${s} with no fallback; core/tokens.css defines
--sf-space-2xs through --sf-space-4xl but does not define --sf-space-3xs.

configurator/src/components/shell/PreviewPanel.svelte[96-97]
configurator/src/components/shell/PreviewPanel.svelte[179-180]
core/tokens.css[173-183]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The preview skin generates spacing demo classes using `var(--sf-space-${s})`, but includes `3xs`, which is not a defined core token. This makes `.pv-space--3xs` compute to an invalid value and the corresponding demo bar renders incorrectly.

## Issue Context
Core spacing tokens start at `--sf-space-2xs`. Some optional component CSS references `--sf-space-3xs` only with a fallback value, implying it is intentionally not guaranteed.

## Fix Focus Areas
- configurator/src/components/shell/PreviewPanel.svelte[96-97]
- configurator/src/components/shell/PreviewPanel.svelte[179-180]

## Suggested fix
Either:
1) Remove `"3xs"` from `SPACES`, or
2) Keep `"3xs"` but special-case it in the generated CSS to use a fallback, e.g. `var(--sf-space-3xs, 0.125rem)` for inline/block size.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

…w skin

SPACES includes "3xs" but core/tokens.css defines spacing only from
--sf-space-2xs up, so .pv-space--3xs referenced an undefined token with no
fallback and the 3xs spacing bar collapsed to its min size instead of showing
the real step. Special-case 3xs with var(--sf-space-3xs, 0.125rem), matching the
fallback the framework already uses for this token elsewhere.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants