Skip to content

fix(preview): dark swatches respect the dark-overrides-enabled toggle - #152

Merged
jackgranatowski merged 3 commits into
mainfrom
claude/repo-issues-closure-HBJBq
May 29, 2026
Merged

fix(preview): dark swatches respect the dark-overrides-enabled toggle#152
jackgranatowski merged 3 commits into
mainfrom
claude/repo-issues-closure-HBJBq

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bug: When the "Custom dark mode colors" toggle was OFF, the live preview still injected explicit --sf-color-*-dark custom properties — from previously stored token values or the default hex-hint fallbacks — regardless of the toggle state. Switching to Dark mode in the preview showed those stored/default colors instead of the auto-derived ones.
  • Fix: inlineStyle now reads dark_overrides_enabled from the colors section and branches:
    • Toggle ON (default): injects stored/hint dark values as before.
    • Toggle OFF: injects the same CSS relative-color-syntax formula the framework uses for auto-derivation, so the preview exactly matches what the browser renders on the front-end.

The formulas mirror core/tokens.css verbatim:

brand/status: oklch(from var(--sf-color-X-light) clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9) h)
base:         oklch(from var(--sf-color-base-light) clamp(0.16, calc(1.18 - l), 0.24) calc(c * 0.5) h)

Test plan

  • Open admin panel → Colors tab
  • Turn OFF the "Custom dark mode colors" toggle
  • Switch the Live Preview to Dark mode — swatches should show the auto-derived dark variants (lighter versions of the light colors, base inverted), not the stored/default dark values
  • Turn the toggle back ON — swatches should immediately revert to stored/hint dark values
  • Confirm no regressions in Light mode swatches either way

https://claude.ai/code/session_019MD9F8rrpYzCeDTmSTLA1K


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Live preview now correctly applies dark-mode color overrides when enabled.
    • When overrides are disabled (or a dark override is missing), dark colors are automatically derived from the light palette so previews remain consistent.

Review Change Stack

When dark overrides are OFF the live preview still injected explicit
--sf-color-*-dark vars (from stored values or default hex-hint
fallbacks), so Dark mode showed wrong colors the framework wouldn't use.

Read dark_overrides_enabled in inlineStyle:
  - ON (default): inject stored/hint dark values as before.
  - OFF: inject the same CSS relative-color formula the framework uses:
    brand/status: oklch(from var(--sf-color-X-light)
      clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9) h)
    base: oklch(from var(--sf-color-base-light)
      clamp(0.16, calc(1.18 - l), 0.24) calc(c * 0.5) h)

https://claude.ai/code/session_019MD9F8rrpYzCeDTmSTLA1K
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 51a35146-a349-47ca-9921-50e32ff57219

📥 Commits

Reviewing files that changed from the base of the PR and between 18312ac and d5ce9e3.

📒 Files selected for processing (2)
  • integrations/bricks/admin-app/src/components/LivePreview.svelte
  • integrations/bricks/assets/admin-app/app.js

📝 Walkthrough

Walkthrough

LivePreview.svelte adds module-level helpers to derive dark color values and changes inline CSS generation to choose dark tokens based on colors.dark_overrides_enabled: use stored *_dark_* (with fallback to derived) when enabled, or always derive dark from light via oklch(from var(...)) when disabled.

Changes

Dark Mode Color Variable Generation

Layer / File(s) Summary
Auto-dark helper functions
integrations/bricks/admin-app/src/components/LivePreview.svelte
Adds module-level autoDarkStandard, autoDarkBase, and autoDark helpers that emit oklch(from var(--sf-color-*-light) ...) strings to derive dark values from light tokens.
Dark color variable generation with override toggle
integrations/bricks/admin-app/src/components/LivePreview.svelte
inlineStyle now gates dark variable emission on colors.dark_overrides_enabled: when true it prefers stored brand_dark_*/status_dark_* values (falling back to the auto-derived values), and when false it derives --sf-color-*-dark exclusively from the corresponding light tokens using the new helpers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • codeslash-dev/SLASHED#26: Implements deriving dark --sf-color-*-dark from light tokens when dark overrides are not set, aligning with the auto-derivation logic introduced here.
  • codeslash-dev/SLASHED#151: Modifies LivePreview dark-mode CSS generation to respect colors.dark_overrides_enabled, overlapping with this PR's gating and fallback behavior.
  • codeslash-dev/SLASHED#25: Updates dark-mode color-token fallback behavior elsewhere in the codebase; related to this PR's change to when and how dark tokens are derived or used.
🚥 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 describes the main change: fixing dark swatches to respect the dark-overrides-enabled toggle in the live preview component.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/repo-issues-closure-HBJBq

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

When the dark-override toggle is ON but only some colors have an
explicit dark value, the preview was falling back to the default
brand_dark_hex_hints — hardcoded palette swatches that don't
reflect the user's customised light colors.

The framework itself falls back to auto-derivation (CSS relative
color syntax) for any --sf-color-*-dark that isn't explicitly set.
The preview now does the same: a stored dark value is used when
present; otherwise the autoDark() formula is applied regardless of
toggle state. This makes partially-overridden palettes render
accurately in both Dark and Light preview modes.

https://claude.ai/code/session_019MD9F8rrpYzCeDTmSTLA1K

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

🧹 Nitpick comments (1)
integrations/bricks/admin-app/src/components/LivePreview.svelte (1)

57-72: ⚡ Quick win

Centralize the derived dark formula to avoid drift from core/tokens.css.

The relative-color formula is inlined three times: brand-base, brand non-base, and status (with brand non-base and status using the same expression). Extract two small helpers so all call sites share one source of truth.

♻️ Proposed refactor

Define once (near the other module-level constants around Line 29):

const brandDark = (light) =>
  `oklch(from var(${light}) clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9) h)`;
const baseDark = (light) =>
  `oklch(from var(${light}) clamp(0.16, calc(1.18 - l), 0.24) calc(c * 0.5) h)`;

Then in the loops:

       } else {
-        const formula = name === 'base'
-          ? `oklch(from var(--sf-color-base-light) clamp(0.16, calc(1.18 - l), 0.24) calc(c * 0.5) h)`
-          : `oklch(from var(--sf-color-${name}-light) clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9) h)`;
-        pairs.push(`--sf-color-${name}-dark:${formula}`);
+        const light = `--sf-color-${name}-light`;
+        pairs.push(`--sf-color-${name}-dark:${name === 'base' ? baseDark(light) : brandDark(light)}`);
       }
-      } else {
-        pairs.push(`--sf-color-${name}-dark:oklch(from var(--sf-color-${name}-light) clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9) h)`);
-      }
+      } else {
+        pairs.push(`--sf-color-${name}-dark:${brandDark(`--sf-color-${name}-light`)}`);
+      }

The framework tokens derive non-base dark with clamp(.65, calc(.95 - l * .5), .88) ... c * .9 and base dark with clamp(.16, calc(1.18 - l), .24) ... c * .5, so this refactor should remain behavior-preserving while reducing copy/paste drift risk.

🤖 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 `@integrations/bricks/admin-app/src/components/LivePreview.svelte` around lines
57 - 72, Extract two module-level helper functions, e.g. brandDark(light) and
baseDark(light), near the other constants around the top of LivePreview.svelte
(around the existing module-level constants) that return the respective derived
dark formulas (base uses clamp(0.16, calc(1.18 - l), 0.24) calc(c * 0.5) and
non-base/status use clamp(0.65, calc(0.95 - l * 0.5), 0.88) calc(c * 0.9)). Then
replace the three inlined formulas in the loops: the base branch where name ===
'base' (currently producing the longer base formula), the brand non-base branch,
and the status else branch (currently producing the non-base/status formula) so
they call baseDark(`--sf-color-${name}-light`) or
brandDark(`--sf-color-${name}-light`) respectively; keep the existing variable
names (pairs, name, statuses, colors, defaultColors, darkEnabled) and preserve
behavior/arguments.
🤖 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 `@integrations/bricks/admin-app/src/components/LivePreview.svelte`:
- Around line 57-72: Extract two module-level helper functions, e.g.
brandDark(light) and baseDark(light), near the other constants around the top of
LivePreview.svelte (around the existing module-level constants) that return the
respective derived dark formulas (base uses clamp(0.16, calc(1.18 - l), 0.24)
calc(c * 0.5) and non-base/status use clamp(0.65, calc(0.95 - l * 0.5), 0.88)
calc(c * 0.9)). Then replace the three inlined formulas in the loops: the base
branch where name === 'base' (currently producing the longer base formula), the
brand non-base branch, and the status else branch (currently producing the
non-base/status formula) so they call baseDark(`--sf-color-${name}-light`) or
brandDark(`--sf-color-${name}-light`) respectively; keep the existing variable
names (pairs, name, statuses, colors, defaultColors, darkEnabled) and preserve
behavior/arguments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a4178607-a9ed-4e8c-9efa-89b9c1a494c8

📥 Commits

Reviewing files that changed from the base of the PR and between d422f21 and 18312ac.

📒 Files selected for processing (2)
  • integrations/bricks/admin-app/src/components/LivePreview.svelte
  • integrations/bricks/assets/admin-app/app.js

Move autoDarkStandard/autoDarkBase/autoDark out of the $derived.by()
closure so they are defined once at module load rather than recreated
on every reactive re-render. Behaviour is unchanged.

https://claude.ai/code/session_019MD9F8rrpYzCeDTmSTLA1K
@jackgranatowski
jackgranatowski merged commit 8d9df73 into main May 29, 2026
5 checks passed
@jackgranatowski
jackgranatowski deleted the claude/repo-issues-closure-HBJBq branch May 31, 2026 18:01
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