[quick-theme] Quick Theme exports only the last selected theme mode (light or dark)
#49,125 建立於 2026年5月19日
描述
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
login/ui
Describe the bug
When using the Quick Theme feature to customize both light and dark mode colors, the exported .jar file only contains the CSS variables for the last selected theme mode. The other mode's values are completely lost.
Version
26.6.2
Regression
- The issue is a regression
Expected behavior
Both light and dark mode color configurations should be preserved in the exported .jar, regardless of which theme mode is currently selected in the UI. The theme-settings.json inside the JAR should contain both "light" and "dark" keys with their respective values, and the generated theme-styles.css should populate both the :root and .pf-v5-theme-dark blocks.
Actual behavior
The theme-settings.json only contains the values for the last selected mode. The other mode is missing entirely. The generated theme-styles.css reflects this — the inactive mode block is empty:
:root {
/* all light mode values here */
}
.pf-v5-theme-dark {
/* completely empty */
}
How to Reproduce?
- Enable the
quick-themefeature (--features=quick-theme). - Go to Realm Settings → Themes → Quick Theme.
- Configure some colors in Light mode.
- Switch the toggle to Dark mode.
- Configure some colors in Dark mode.
- Click Download theme JAR.
- Extract the JAR and inspect
theme-settings.json— only the dark mode values are present.
Anything else?
This regression was introduced in PR #46247, which merged the previously separate light/dark theme tabs into a single component with an internal toggle. The useEffect hook in ThemeColors.tsx has theme as a dependency:
useEffect(() => {
setupForm();
switchTheme(theme);
return () => { switchTheme(originalTheme); };
}, [realm, theme]); // ← theme is a dependency
When the user toggles between light and dark, theme changes, the effect re-runs, setupForm() is called, which calls reset(), which calls:
form.reset({ [theme]: mapping.reduce(...) });
This only populates the form with the currently active theme's values, wiping the other theme's data from the form state. Since convert() serializes the form state into theme-settings.json, the inactive theme is never included in the export.