Skip to content

feat(desktop): configurable light/dark themes for system mode#2557

Merged
Kitenite merged 4 commits into
superset-sh:mainfrom
Roshvan:Roshvan/light-mode-dark-mode-choice
Mar 26, 2026
Merged

feat(desktop): configurable light/dark themes for system mode#2557
Kitenite merged 4 commits into
superset-sh:mainfrom
Roshvan:Roshvan/light-mode-dark-mode-choice

Conversation

@Roshvan
Copy link
Copy Markdown
Contributor

@Roshvan Roshvan commented Mar 18, 2026

Summary

image image

When "System" theme is selected, users can now choose which specific theme to use for light and dark OS modes via dropdowns on the System card, instead of always resolving to the built-in light/dark themes.

Changes

  • Added systemLightThemeId / systemDarkThemeId to theme state (persistence schema, tRPC schema, zustand store)
  • Updated resolveThemeId to use user-configured preferences instead of hardcoded "light"/"dark"
  • System theme card shows two <Select> dropdowns (all themes listed) when selected
  • Deleting a custom theme that was set as a system preference resets it to the built-in default

Test plan

  • Select "System" theme card → verify two dropdowns appear for "Light theme" and "Dark theme"
  • Set dark theme to "Monokai", verify: when OS is in dark mode, Monokai is applied
  • Toggle OS dark/light mode → verify theme switches to the correct user-selected theme
  • Restart app → verify preferences persist
  • Import a custom theme → verify it appears in both dropdowns
  • Delete a custom theme set as a system preference → verify it resets to built-in default

Summary by cubic

Adds configurable theme mapping for System mode so users can pick which themes apply in OS light and dark modes. Includes validation and fallbacks to keep System stable across restarts, deletions, and bad inputs.

  • New Features

    • Added systemLightThemeId and systemDarkThemeId to app state, tRPC schema, and persistence; defaults to light/dark.
    • system now resolves to these IDs based on OS preference and re-resolves on OS changes, preference updates, deletions, and app start.
    • System card shows two @superset/ui/select dropdowns for Light and Dark; previews use getTerminalColors. Hooks: useSystemLightThemeId, useSystemDarkThemeId, useSetSystemThemePreference.
  • Bug Fixes

    • Validate stale/missing system theme IDs and fall back to built-in light/dark; normalize on hydration so System stays active.
    • Reject invalid or system IDs in setSystemThemePreference; ignore bad inputs from non-UI callers.
    • Reset preferences if a selected theme is deleted and re-apply the resolved theme; extracted DEFAULT_LIGHT_THEME_ID/DEFAULT_DARK_THEME_ID constants.

Written for commit 6bfcd3c. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Distinct themes for system light and dark modes so different themes activate with OS preference.
    • Appearance settings let you pick separate light and dark system-theme preferences from available themes with clearer selection feedback.
    • New controls persist and restore system theme preferences across sessions with sensible defaults and automatic fallbacks if a theme is missing.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds per-mode system theme preferences: two new fields (systemLightThemeId, systemDarkThemeId) are persisted and initialized; store logic updated to resolve and set system-mode themes; new hooks exposed; UI components updated to let users pick light/dark theme mappings.

Changes

Cohort / File(s) Summary
Schema & App State
apps/desktop/src/lib/trpc/routers/ui-state/index.ts, apps/desktop/src/main/lib/app-state/schemas.ts
Added optional systemLightThemeId and systemDarkThemeId to persisted ThemeState and defaults in app state.
Theme Store Logic
apps/desktop/src/renderer/stores/theme/store.ts
Added systemLightThemeId / systemDarkThemeId to ThemeState; added setSystemThemePreference(mode, themeId); updated resolveThemeId to consider per-mode system IDs and custom themes; reset mappings when removing themes; persist/rehydrate new fields; initialize defaults and log unresolved theme errors.
Theme Store Exports
apps/desktop/src/renderer/stores/theme/index.ts
Re-exported new hooks: useSetSystemThemePreference, useSystemDarkThemeId, useSystemLightThemeId.
Appearance Settings UI
apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx
Refactored SystemThemeCard to accept darkTheme, lightTheme, allThemes, and onSystemThemePreferenceChange; added light/dark selectors and selection indicator; updated preview rendering and layout.
Theme Section Integration
apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/ThemeSection/ThemeSection.tsx
Wired store hooks (useSystemLightThemeId, useSystemDarkThemeId, useSetSystemThemePreference), resolved system themes with fallbacks (defaults), and passed themes + handler into SystemThemeCard.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as SystemThemeCard
    participant Section as ThemeSection
    participant Store as ThemeStore
    participant Persist as Persistence

    User->>UI: select system light/dark mapping
    UI->>Section: onSystemThemePreferenceChange(mode, themeId)
    Section->>Store: setSystemThemePreference(mode, themeId)
    Store->>Store: update systemLightThemeId/systemDarkThemeId
    Store->>Store: re-resolve active theme (OS mode + system IDs)
    Store->>Persist: persist updated theme state
    Persist-->>Store: persisted
    Store-->>Section: state change via hook
    Section-->>UI: re-render with resolved themes
    UI-->>User: updated preview/controls
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibble keys and hop about,
Two tiny IDs, no doubt.
Light for dawn, dark for night,
I tuck them in so themes take flight,
Hooray — the system matches sight! 🎨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding configurable light/dark theme options for system mode, which is the primary focus of the changeset.
Description check ✅ Passed The pull request description is comprehensive and well-structured, including a clear summary with screenshots, detailed changes, and an explicit test plan with checkboxes.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx:165">
P2: System theme selectors include themes with optional/missing `terminal` colors, but the card returns `null` if either selected theme lacks `terminal`, causing the entire System card to disappear.</violation>
</file>

<file name="apps/desktop/src/renderer/stores/theme/store.ts">

<violation number="1" location="apps/desktop/src/renderer/stores/theme/store.ts:275">
P2: Deleting a custom theme used by system mode does not immediately re-resolve and apply the fallback theme, leaving stale active theme state.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/desktop/src/renderer/stores/theme/store.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/desktop/src/renderer/stores/theme/store.ts (1)

312-325: Consider cleaning up the media query listener on store destruction.

The addEventListener for OS theme preference changes is set up but never removed. While this is typically fine for a singleton store that lives for the app's lifetime, adding a cleanup mechanism would be more robust, especially for testing scenarios.

♻️ Optional: Store cleanup reference
+				// Store reference for potential cleanup
+				let mediaQueryCleanup: (() => void) | null = null;
+
 				// Set up listener for OS theme preference changes
 				if (typeof window !== "undefined") {
 					const mediaQuery = window.matchMedia(
 						"(prefers-color-scheme: dark)",
 					);
 					const handleChange = () => {
 						const currentState = get();
 						// Only update if system theme is selected
 						if (currentState.activeThemeId === SYSTEM_THEME_ID) {
 							currentState.setTheme(SYSTEM_THEME_ID);
 						}
 					};
 					mediaQuery.addEventListener("change", handleChange);
+					mediaQueryCleanup = () => mediaQuery.removeEventListener("change", handleChange);
 				}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/theme/store.ts` around lines 312 - 325, The
mediaQuery change listener added in the store
(window.matchMedia("(prefers-color-scheme: dark)") with addEventListener and
handleChange) is never removed; modify the store to keep references to
mediaQuery and handleChange and remove the listener on store teardown (e.g.,
implement an unsubscribe/cleanup method returned from the store factory or a
destroy method that calls mediaQuery.removeEventListener("change",
handleChange)), ensuring get(), SYSTEM_THEME_ID, and setTheme logic remain
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/ThemeSection/ThemeSection.tsx`:
- Around line 46-49: The fallbacks for systemLightTheme and systemDarkTheme
currently use defaultLightTheme/defaultDarkTheme which lack terminal colors and
make SystemThemeCard return null; update the fallback logic in the ThemeSection
where systemLightTheme and systemDarkTheme are computed to instead (1) try to
find the theme by id in allThemes, (2) if not found, select the first theme in
allThemes with the matching type (light/dark), and (3) if still not found, fall
back to a builtInThemes entry that includes terminal colors (e.g., from
builtInThemes filtered by id or type) so SystemThemeCard always receives a theme
object with terminal properties. Ensure you reference and adjust the variables
systemLightTheme, systemDarkTheme, allThemes,
defaultLightTheme/defaultDarkTheme, and builtInThemes when implementing this
change.

---

Nitpick comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 312-325: The mediaQuery change listener added in the store
(window.matchMedia("(prefers-color-scheme: dark)") with addEventListener and
handleChange) is never removed; modify the store to keep references to
mediaQuery and handleChange and remove the listener on store teardown (e.g.,
implement an unsubscribe/cleanup method returned from the store factory or a
destroy method that calls mediaQuery.removeEventListener("change",
handleChange)), ensuring get(), SYSTEM_THEME_ID, and setTheme logic remain
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7d071061-5d27-4e1e-85b0-f7e448a3f4ac

📥 Commits

Reviewing files that changed from the base of the PR and between cbea37d and 6d3b3f0.

📒 Files selected for processing (6)
  • apps/desktop/src/lib/trpc/routers/ui-state/index.ts
  • apps/desktop/src/main/lib/app-state/schemas.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/ThemeSection/ThemeSection.tsx
  • apps/desktop/src/renderer/stores/theme/index.ts
  • apps/desktop/src/renderer/stores/theme/store.ts

@Roshvan Roshvan force-pushed the Roshvan/light-mode-dark-mode-choice branch from 6d3b3f0 to e6779ce Compare March 18, 2026 02:26
@Roshvan
Copy link
Copy Markdown
Contributor Author

Roshvan commented Mar 18, 2026

@Kitenite Heads up — looks like this is a duplicate of work in #2548 / #2547. Feel free to close this one if you'd like to keep the other, or keep whichever you prefer. Don't mind either way!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/desktop/src/renderer/stores/theme/store.ts (1)

173-199: Add regression coverage for the new system-theme branches.

These paths now own the core behaviors in this feature: re-resolving the active theme for the current OS mode, resetting deleted custom preferences, and restoring those preferences after hydration. A small co-located store test around those cases would make this much safer to evolve.

As per coding guidelines, "**/*.{ts,tsx}: Co-locate tests with their implementation files (e.g., Component.test.tsx next to Component.tsx)."

Also applies to: 257-298, 352-360

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/theme/store.ts` around lines 173 - 199, Add
co-located unit tests for the new system-theme branches in the store (tests next
to store.ts) that exercise setSystemThemePreference and the re-resolve logic
when activeThemeId === SYSTEM_THEME_ID: mock/construct store state with
systemLightThemeId/systemDarkThemeId and customThemes, change light and dark
preferences, verify resolveThemeId is invoked (via expected resolvedId), that
findTheme returns the theme and applyTheme produces terminalTheme, and that set
updates activeTheme and terminalTheme; include cases for resetting deleted
custom preferences and restoring preferences after hydration to cover the other
branches mentioned (also add tests around the other ranges referenced: 257-298
and 352-360).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 76-84: resolveThemeId currently trusts
systemLightThemeId/systemDarkThemeId verbatim which can reference deleted or
missing themes; validate those IDs against the store's available themes (e.g.,
the themes list/map used by initializeTheme) and if an ID is not found replace
it with the known built-in light/dark fallback IDs before using them; apply the
same validation/fallback logic in initializeTheme (and the other block noted
around lines 316-330) so the store never silently drops System mode — use
resolveThemeId and initializeTheme to perform the check against the themes
registry and substitute the built-in light/dark IDs when necessary.

---

Nitpick comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 173-199: Add co-located unit tests for the new system-theme
branches in the store (tests next to store.ts) that exercise
setSystemThemePreference and the re-resolve logic when activeThemeId ===
SYSTEM_THEME_ID: mock/construct store state with
systemLightThemeId/systemDarkThemeId and customThemes, change light and dark
preferences, verify resolveThemeId is invoked (via expected resolvedId), that
findTheme returns the theme and applyTheme produces terminalTheme, and that set
updates activeTheme and terminalTheme; include cases for resetting deleted
custom preferences and restoring preferences after hydration to cover the other
branches mentioned (also add tests around the other ranges referenced: 257-298
and 352-360).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f895d46a-b743-489f-82d1-dbdf133cd8f7

📥 Commits

Reviewing files that changed from the base of the PR and between 6d3b3f0 and e6779ce.

📒 Files selected for processing (6)
  • apps/desktop/src/lib/trpc/routers/ui-state/index.ts
  • apps/desktop/src/main/lib/app-state/schemas.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/ThemeSection/ThemeSection.tsx
  • apps/desktop/src/renderer/stores/theme/index.ts
  • apps/desktop/src/renderer/stores/theme/store.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/desktop/src/lib/trpc/routers/ui-state/index.ts
  • apps/desktop/src/renderer/stores/theme/index.ts
  • apps/desktop/src/main/lib/app-state/schemas.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx

Comment thread apps/desktop/src/renderer/stores/theme/store.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 182-207: setSystemThemePreference currently accepts and persists
any themeId (risking invalid state); validate the incoming themeId against the
store's available/custom themes before calling set. Inside
setSystemThemePreference, use get() to access state.customThemes (or whichever
canonical list you maintain), check that the provided themeId exists (e.g.,
findTheme(themeId, state.customThemes) or equivalent) and only call set(updates)
when valid; if invalid, skip persisting (or return/error) and do not attempt to
re-resolve SYSTEM_THEME_ID or call resolveThemeId/findTheme/applyTheme with
invalid IDs. Ensure you still re-resolve and apply the theme only using
validated newLightId/newDarkId values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6849e173-34cf-45f4-8c6b-6c0e3b70eac2

📥 Commits

Reviewing files that changed from the base of the PR and between e6779ce and 506f280.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/SystemThemeCard/SystemThemeCard.tsx
  • apps/desktop/src/renderer/stores/theme/store.ts

Comment thread apps/desktop/src/renderer/stores/theme/store.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
apps/desktop/src/renderer/stores/theme/store.ts (2)

182-215: Please add co-located tests for the new system preference flows.

This change adds multiple critical branches (validation, stale normalization, deletion resets, runtime re-resolution). A co-located store test file would lock behavior and prevent regressions.

As per coding guidelines: **/*.{ts,tsx}: Co-locate tests with their implementation files (e.g., Component.test.tsx next to Component.tsx).

Also applies to: 274-317, 332-390

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/theme/store.ts` around lines 182 - 215, Add
co-located unit tests next to store.ts that exercise setSystemThemePreference
and the related flows: validation (rejecting SYSTEM_THEME_ID or missing
findTheme), updating systemLightThemeId/systemDarkThemeId, behavior when
activeThemeId === SYSTEM_THEME_ID including stale normalization and
re-resolution via resolveThemeId, and confirming applyTheme and set are called
to update activeTheme/terminalTheme; write tests that mock or provide
customThemes and assert state changes for all branches (validation early return,
light update, dark update, and runtime re-resolution using findTheme,
resolveThemeId, and applyTheme) to prevent regressions.

86-87: Extract built-in system fallback IDs into shared constants.

"light" / "dark" are repeated in several branches; centralizing them (e.g., SYSTEM_LIGHT_FALLBACK_ID, SYSTEM_DARK_FALLBACK_ID) would reduce drift risk during future refactors.

Also applies to: 153-154, 285-290, 346-349

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/theme/store.ts` around lines 86 - 87, The
code repeats literal theme IDs "light" and "dark" (e.g., where fallbackId is set
and other branches in store.ts) — extract these into shared constants (for
example SYSTEM_LIGHT_FALLBACK_ID and SYSTEM_DARK_FALLBACK_ID) and replace all
literal occurrences with those constants (update places referenced around the
fallbackId assignment and the other branches noted at lines ~153-154, ~285-290,
~346-349). Ensure the constants are exported from a central module or the same
file if intended for local use, update imports/usages (e.g., where fallbackId,
system preference handling, and any map/lookup use the literals), and run
tests/build to confirm no missing references.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 182-215: Add co-located unit tests next to store.ts that exercise
setSystemThemePreference and the related flows: validation (rejecting
SYSTEM_THEME_ID or missing findTheme), updating
systemLightThemeId/systemDarkThemeId, behavior when activeThemeId ===
SYSTEM_THEME_ID including stale normalization and re-resolution via
resolveThemeId, and confirming applyTheme and set are called to update
activeTheme/terminalTheme; write tests that mock or provide customThemes and
assert state changes for all branches (validation early return, light update,
dark update, and runtime re-resolution using findTheme, resolveThemeId, and
applyTheme) to prevent regressions.
- Around line 86-87: The code repeats literal theme IDs "light" and "dark"
(e.g., where fallbackId is set and other branches in store.ts) — extract these
into shared constants (for example SYSTEM_LIGHT_FALLBACK_ID and
SYSTEM_DARK_FALLBACK_ID) and replace all literal occurrences with those
constants (update places referenced around the fallbackId assignment and the
other branches noted at lines ~153-154, ~285-290, ~346-349). Ensure the
constants are exported from a central module or the same file if intended for
local use, update imports/usages (e.g., where fallbackId, system preference
handling, and any map/lookup use the literals), and run tests/build to confirm
no missing references.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4682119a-51b6-4951-9ebf-97f73eb00645

📥 Commits

Reviewing files that changed from the base of the PR and between 506f280 and 87c29b4.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/stores/theme/store.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/desktop/src/renderer/stores/theme/store.ts (1)

188-221: Consider batching store updates in setSystemThemePreference.

When system mode is active, this path can call set(...) twice. Combining into one write avoids extra subscriber notifications/rerenders.

♻️ Suggested batching refactor
 setSystemThemePreference: (mode: "light" | "dark", themeId: string) => {
   const state = get();
   if (
     themeId === SYSTEM_THEME_ID ||
     !findTheme(themeId, state.customThemes)
   ) {
     return;
   }
   const updates =
     mode === "light"
       ? { systemLightThemeId: themeId }
       : { systemDarkThemeId: themeId };

-  set(updates);
-
-  // Re-resolve if system theme is currently active
-  if (state.activeThemeId === SYSTEM_THEME_ID) {
+  // Re-resolve if system theme is currently active
+  if (state.activeThemeId === SYSTEM_THEME_ID) {
     const newLightId =
       mode === "light" ? themeId : state.systemLightThemeId;
     const newDarkId =
       mode === "dark" ? themeId : state.systemDarkThemeId;
     const resolvedId = resolveThemeId(
       SYSTEM_THEME_ID,
       newLightId,
       newDarkId,
       state.customThemes,
     );
     const theme = findTheme(resolvedId, state.customThemes);
     if (theme) {
       const { terminalTheme } = applyTheme(theme);
-      set({ activeTheme: theme, terminalTheme });
+      set({ ...updates, activeTheme: theme, terminalTheme });
+      return;
     }
   }
+  set(updates);
 },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/theme/store.ts` around lines 188 - 221,
setSystemThemePreference currently calls set(...) twice when the system theme is
active (once to update systemLightThemeId/systemDarkThemeId and again to set
activeTheme/terminalTheme), causing extra subscriber notifications; change it to
compute the new state first (derive newLightId/newDarkId, call resolveThemeId
and applyTheme) and then call set once with a combined update object that
includes the systemLightThemeId/systemDarkThemeId fields plus activeTheme and
terminalTheme as needed; update references inside setSystemThemePreference (get,
set, SYSTEM_THEME_ID, systemLightThemeId, systemDarkThemeId, resolveThemeId,
applyTheme, findTheme) so the single set merges both the preference change and
any re-resolved activeTheme in one write.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/desktop/src/renderer/stores/theme/store.ts`:
- Around line 188-221: setSystemThemePreference currently calls set(...) twice
when the system theme is active (once to update
systemLightThemeId/systemDarkThemeId and again to set
activeTheme/terminalTheme), causing extra subscriber notifications; change it to
compute the new state first (derive newLightId/newDarkId, call resolveThemeId
and applyTheme) and then call set once with a combined update object that
includes the systemLightThemeId/systemDarkThemeId fields plus activeTheme and
terminalTheme as needed; update references inside setSystemThemePreference (get,
set, SYSTEM_THEME_ID, systemLightThemeId, systemDarkThemeId, resolveThemeId,
applyTheme, findTheme) so the single set merges both the preference change and
any re-resolved activeTheme in one write.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40ea7a98-7f1b-434d-975a-f0880bab55ec

📥 Commits

Reviewing files that changed from the base of the PR and between 87c29b4 and 0598a4c.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/stores/theme/store.ts

@Roshvan Roshvan force-pushed the Roshvan/light-mode-dark-mode-choice branch 2 times, most recently from 0bb0652 to f5e77d8 Compare March 22, 2026 16:05
@Roshvan
Copy link
Copy Markdown
Contributor Author

Roshvan commented Mar 23, 2026

@Kitenite what did we want to do with this plan to merge at some point or should I close?

@Kitenite
Copy link
Copy Markdown
Collaborator

I think we could probably merge it. Is there a preference between this and the other implementation?

@Roshvan
Copy link
Copy Markdown
Contributor Author

Roshvan commented Mar 23, 2026

I think we could probably merge it. Is there a preference between this and the other implementation?

Seem similar implementations I have not pulled down and tested or seen what the ui looks like on his implementation I don't mind either

@Roshvan
Copy link
Copy Markdown
Contributor Author

Roshvan commented Mar 24, 2026

@AviPeltz want to take a look here?

Roshvan added 4 commits March 26, 2026 07:47
When "System" theme is selected, users can now choose which specific
theme to use for light and dark modes via dropdowns on the System card,
instead of always resolving to the built-in light/dark themes.
…or fallbacks

resolveThemeId now validates that persisted system theme IDs reference existing
themes, falling back to built-in light/dark when stale. initializeTheme
normalizes stale IDs on hydration so system mode is never silently dropped.
SystemThemeCard uses getTerminalColors() for guaranteed terminal colors instead
of accessing the optional .terminal property directly.
…sisting

Reject invalid or recursive "system" IDs to prevent inconsistent persisted
state from non-UI callers.
Replace repeated "light"/"dark" literals with DEFAULT_LIGHT_THEME_ID and
DEFAULT_DARK_THEME_ID to reduce drift risk during future refactors.
@Roshvan Roshvan force-pushed the Roshvan/light-mode-dark-mode-choice branch from f5e77d8 to 6bfcd3c Compare March 26, 2026 12:53
@Kitenite Kitenite merged commit b9b9ea8 into superset-sh:main Mar 26, 2026
1 check passed
@Kitenite
Copy link
Copy Markdown
Collaborator

Let's ball!

@Roshvan
Copy link
Copy Markdown
Contributor Author

Roshvan commented Mar 26, 2026

Let's ball!

Love it LOL

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