Sync Studio light-mode support into the admin-app - #154
Conversation
Vendors the completed SLASHED framework light-mode rollout (codeslash-dev/SLASHED PRs #506, #507, #508, #510 — theme system, Sun/Moon toggle, and light-mode Tailwind pairings across the whole Studio chrome and every panel) and rebuilds the admin SPA bundle. Also pins AppOverlay.svelte's root to the `dark` class: it reuses SidebarNav/DomainPanel/CommandPalette from the vendored core, which now default to light unless an ancestor opts into dark via Tailwind's class-based dark variant. The frontend overlay's own shell markup is plugin-specific and still hardcoded dark, so forcing `dark` on its root keeps the embedded components visually consistent with it instead of mismatching (light nav inside a dark shell).
|
Warning Review limit reached
Next review available in: 58 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR adds a persisted light/dark theme controller ( ChangesDark/light theme support
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant MainTs as main.ts
participant PluginMainTs as plugin-main.ts
participant ThemeModule as theme.svelte.ts
participant DomRoot as App root element
MainTs->>ThemeModule: bindThemeRoot(target)
ThemeModule->>ThemeModule: readStored() / systemTheme()
ThemeModule->>DomRoot: applyToRoot() toggles "dark" class
PluginMainTs->>ThemeModule: themeState.value = "dark"
ThemeModule->>DomRoot: applyToRoot() forces dark for overlay
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 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 QodoSync Studio light-mode support into the admin-app
AI Description
Diagram
High-Level Assessment
Files changed (38)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
5 rules 1. Overlay option theme mismatch
|
| import { themeState } from '../../lib/theme.svelte'; | ||
|
|
||
| type RatioPreset = { label: string; value: number }; | ||
|
|
||
| // <option> only reliably accepts a background via inline style (no dark: | ||
| // variant support), so it's derived from the chrome theme directly. | ||
| let optionBg = $derived(themeState.value === 'dark' ? '#16161e' : '#ffffff'); | ||
|
|
There was a problem hiding this comment.
2. Overlay option theme mismatch 🐞 Bug ≡ Correctness
Several panels derive native <option> background color from themeState, but the WordPress front-end overlay is forced into a dark Tailwind context via a hardcoded dark class and never synchronizes themeState to dark. On pages where the admin app isn’t mounted (so no theme root is bound), themeState stays storage/OS-derived (often light), producing inconsistent dropdown option styling in the dark overlay (browser-dependent severity).
Agent Prompt
## Issue description
The WP front-end overlay forces a dark UI via a hardcoded `dark` class, but components compute some native `<option>` styling from `themeState`, which can remain light/system-derived when the main admin app is not mounted. This leads to inconsistent dropdown styling in the overlay.
## Issue Context
- The overlay is mounted on pages where `main.ts` often does not mount anything, so `bindThemeRoot()` is never called.
- Panels use `themeState` to set inline `<option>` backgrounds because Tailwind dark variants don’t reliably apply to `<option>`.
## Fix Focus Areas
- Add a non-persisting API to set theme and stop following the system (e.g. `setTheme(t, { persist: false })` or `forceTheme(t)`), so the overlay can pin `themeState` to `'dark'` without writing `localStorage`.
- Call that API from the overlay mount path (only when `#slashed-frontend-overlay` exists), before/when mounting `AppOverlay`.
### Fix Focus Areas (code references)
- SLASHED-for-WP/admin-app/src/lib/theme.svelte.ts[12-59]
- SLASHED-for-WP/admin-app/src/plugin-main.ts[34-58]
- SLASHED-for-WP/admin-app/src/components/inputs/ClampField.svelte[9-16]
- SLASHED-for-WP/admin-app/src/AppOverlay.svelte[322-327]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
- Ignore admin-app/src/app.css in stylelint: it's entirely vendored from the framework's Tailwind v4 setup (@custom-variant, an at-rule this project's stylelint-config-standard doesn't know), same as how the framework's own .stylelintrc.json excludes configurator/ entirely. Was failing "Lint, test, version & drift checks" CI. - Pin themeState to 'dark' when mounting the WP frontend overlay (plugin-main.ts, not vendored). The overlay's shell is hardcoded to Tailwind's dark class and never gets a light-mode pass, but components that read themeState.value directly for native elements (e.g. ClampField's <option> background, which can't take a dark: class variant) were left following the OS/wp-admin-saved preference instead, since nothing in the overlay's mount path touched it (Qodo review finding).
57a8b96 to
67cb731
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
SLASHED-for-WP/admin-app/src/components/panels/LayoutPanel.svelte (1)
4-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider centralizing the
optionBgderivation.This exact
optionBgderived value (and its comment) is duplicated verbatim acrossLayoutPanel.svelte,MotionPanel.svelte,TypographyPanel.svelte,WcagPanel.svelte, and likely other panels in this rollout. Consider exporting a sharedoptionBgderived (or a helper function) fromtheme.svelte.tsalongsidethemeStateso all consumers import one implementation instead of re-declaring it.♻️ Example centralization in theme.svelte.ts
export const themeState = $state<{ value: Theme }>({ value: stored ?? systemTheme() }); + +// <option> only reliably accepts a background via inline style (no dark: +// variant support), so panels derive it from the chrome theme directly. +export const optionBg = $derived(themeState.value === 'dark' ? '`#16161e`' : '`#ffffff`');🤖 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 `@SLASHED-for-WP/admin-app/src/components/panels/LayoutPanel.svelte` around lines 4 - 8, The optionBg derived value and its explanatory comment are duplicated across multiple panel components, so centralize that logic in the shared theme module. Move the shared option background derivation into theme.svelte.ts alongside themeState as an exported derived/helper, then update LayoutPanel.svelte and the other panel components (such as MotionPanel.svelte, TypographyPanel.svelte, and WcagPanel.svelte) to import and use that single implementation instead of re-declaring it.
🤖 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 `@SLASHED-for-WP/admin-app/src/components/inputs/SliderRow.svelte`:
- Around line 88-98: The dark-mode helper text in SliderRow.svelte is using the
wrong shade class on the `default: {rawDefault}` paragraph, making it too dark
in dark mode. Update the conditional helper line inside `SliderRow` so the dark
theme token is a lighter slate value instead of `dark:text-slate-700`, keeping
the default label readable while preserving the existing light-mode styling.
In `@SLASHED-for-WP/admin-app/src/components/panels/CheatsheetPanel.svelte`:
- Around line 92-104: The search input in CheatsheetPanel.svelte is missing a
dark-mode placeholder style, so the hint stays too dim on dark backgrounds.
Update the search box class list on the input element to include a dark
placeholder variant alongside the existing placeholder:text-slate-600, keeping
the styling consistent with the rest of the dark theme. Use the input’s existing
class attribute in CheatsheetPanel.svelte to locate the fix.
In `@SLASHED-for-WP/admin-app/src/components/panels/HomePanel.svelte`:
- Around line 158-165: The quick-save input in HomePanel.svelte is missing a
dark-mode placeholder style, so its prompt is too low-contrast on the dark
background. Update the input class list next to the quick-save button to include
a dark placeholder variant alongside the existing placeholder:text-slate-600
styling, keeping the current visual design consistent in both themes.
In `@SLASHED-for-WP/admin-app/src/components/panels/ThemesPanel.svelte`:
- Around line 48-54: The save form in ThemesPanel.svelte has dark-mode contrast
issues: the Theme name input placeholder and the empty-state copy still use
light-only slate colors on dark surfaces. Update the input’s placeholder styling
and the empty-state text styles in ThemesPanel so they use appropriate dark-mode
variants, keeping the save form consistent with the rest of the panel.
In `@SLASHED-for-WP/admin-app/src/plugin-main.ts`:
- Around line 44-53: The dark-theme pin in plugin-main’s theme setup is being
undone because assigning themeState.value = 'dark' still leaves system following
active. Update the theme initialization to use the existing pinning logic or
equivalent in themeState/bindThemeRoot so followSystem is disabled while the
overlay is open, instead of doing a raw value assignment.
---
Nitpick comments:
In `@SLASHED-for-WP/admin-app/src/components/panels/LayoutPanel.svelte`:
- Around line 4-8: The optionBg derived value and its explanatory comment are
duplicated across multiple panel components, so centralize that logic in the
shared theme module. Move the shared option background derivation into
theme.svelte.ts alongside themeState as an exported derived/helper, then update
LayoutPanel.svelte and the other panel components (such as MotionPanel.svelte,
TypographyPanel.svelte, and WcagPanel.svelte) to import and use that single
implementation instead of re-declaring it.
🪄 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: 9b6ce5c7-fac3-4e7d-afd5-6b61bee5bc84
📒 Files selected for processing (40)
.stylelintrc.jsonSLASHED-for-WP/admin-app/.vendored-manifest.jsonSLASHED-for-WP/admin-app/src/App.svelteSLASHED-for-WP/admin-app/src/AppOverlay.svelteSLASHED-for-WP/admin-app/src/app.cssSLASHED-for-WP/admin-app/src/components/CommandPalette.svelteSLASHED-for-WP/admin-app/src/components/DomainPanel.svelteSLASHED-for-WP/admin-app/src/components/inputs/ClampField.svelteSLASHED-for-WP/admin-app/src/components/inputs/ColorInput.svelteSLASHED-for-WP/admin-app/src/components/inputs/OklchColorDesk.svelteSLASHED-for-WP/admin-app/src/components/inputs/PowerKnobRow.svelteSLASHED-for-WP/admin-app/src/components/inputs/RangeWithNumber.svelteSLASHED-for-WP/admin-app/src/components/inputs/SliderRow.svelteSLASHED-for-WP/admin-app/src/components/inputs/TokenRow.svelteSLASHED-for-WP/admin-app/src/components/panels/AllTokensTab.svelteSLASHED-for-WP/admin-app/src/components/panels/BordersPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/CheatsheetPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/ColorsPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/EffectsPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/ExportPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/GenericTokenPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/HomePanel.svelteSLASHED-for-WP/admin-app/src/components/panels/LayoutPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/MacrosPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/MiscPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/MotionPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/ShadowsPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/SpacingPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/ThemesPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/TypographyPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/WcagPanel.svelteSLASHED-for-WP/admin-app/src/components/shell/PreviewPanel.svelteSLASHED-for-WP/admin-app/src/components/shell/SidebarNav.svelteSLASHED-for-WP/admin-app/src/components/shell/StatusBar.svelteSLASHED-for-WP/admin-app/src/components/shell/StudioHeader.svelteSLASHED-for-WP/admin-app/src/lib/theme.svelte.tsSLASHED-for-WP/admin-app/src/main.tsSLASHED-for-WP/admin-app/src/plugin-main.tsSLASHED-for-WP/assets/admin-app/app.cssSLASHED-for-WP/assets/admin-app/app.js
- Switch the frontend overlay's theme pin from a raw themeState.value assignment to forceTheme(), now that SLASHED#512 (which added it) is merged. The raw assignment left followSystem enabled, so a later OS prefers-color-scheme change could flip the overlay back to light while it's open (CodeRabbit review finding). - Sync 4 dark-mode contrast fixes from the framework (codeslash-dev/SLASHED#513): SliderRow's inverted helper-text shade, and missing dark:placeholder/text variants in CheatsheetPanel, HomePanel, and ThemesPanel.
Follow-up to the closed #148, which depended on the framework PR (#500) before it was split for reviewability. That split is now fully merged into
codeslash-dev/SLASHED'smainacross #506, #507, #508, and a final #510 (landing a stacked-merge gap where #507/#508 had merged into intermediate feature branches instead ofmain— see that PR's description for details).What this PR does
theme.svelte.ts), the Sun/Moon toggle in the header, and light-mode Tailwind pairings across the whole Studio shell and every domain panel.assets/admin-app/app.js+app.css.AppOverlay.svelte's root to thedarkclass (plugin-specific, not vendored). It reusesSidebarNav/DomainPanel/CommandPalettefrom the vendored core, which now default to light unless an ancestor opts into dark via Tailwind's class-baseddark:variant. The frontend overlay's own shell markup is still hardcoded dark, so this keeps the embedded components visually consistent with it instead of mismatching (light nav inside a dark shell). A full light-mode pass for the overlay itself is out of scope here — same as the original feat: add light/dark theme toggle to studio chrome #148.Verification
npx svelte-check— 0 errors (the 1 pre-existingplugin-main.tserror is unrelated, confirmed present on a cleanmaincheckout before this change)npm run build:admin-app— builds cleanlynpm test— 142/142 passingnpm run check— admin-app sync drift check passes (thevariables-hints.jsonstaleness it also reports is pre-existing, unrelated to this change)Generated by Claude Code
Summary by CodeRabbit