[Studio] feat: add centralized ThemeContext and useTheme hook for dark mode management#435
Merged
lizhimins merged 3 commits intoJul 17, 2026
Conversation
zhaohai666
force-pushed
the
feature/studio-theme-context
branch
2 times, most recently
from
July 16, 2026 06:36
52bc1d0 to
8023ab1
Compare
…e to localStorage - Create ThemeContext.tsx with React Context pattern (consistent with LangContext) - Provide useTheme hook: darkMode, setDarkMode, toggleTheme - Persist theme preference to localStorage with system preference fallback - Refactor MainLayout.tsx: replace local useState with useTheme hook - Elevate ConfigProvider theme logic to main.tsx for global dark mode support - Remove redundant ConfigProvider wrapper from MainLayout.tsx
- Add vitest + @testing-library/react + @testing-library/user-event dev dependencies - Configure vitest in vite.config.ts with jsdom environment - Add test setup file with jest-dom matchers and localStorage cleanup - Add ThemeContext unit tests (8 cases): - default light mode with no stored preference - read dark/light mode from localStorage - toggle between dark and light - persist theme to localStorage after toggle - setDarkMode(true/false) direct control
zhaohai666
force-pushed
the
feature/studio-theme-context
branch
from
July 17, 2026 08:43
94bdcdd to
374c8a7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduce centralized theme management built on React Context, refactor scattered local dark mode
useStateinsideMainLayout. The exporteduseThemehook exposesdarkMode,setDarkModeandtoggleTheme, following the same design pattern as existinguseLangi18n hook.Changes
web/src/theme/ThemeContext.tsxThemeProvideranduseThemehook with TypeScript. Load initial theme preference fromlocalStorage, fall back to systemprefers-color-scheme. Automatically persist updated selection tolocalStorage.web/src/layouts/MainLayout.tsxuseState(false)dark mode state, consume shared state viauseTheme(). Delete redundant inlineConfigProvidertheme wrapper (moved globally). Replace manual() => setDarkMode(!darkMode)calls with built-intoggleTheme.web/src/main.tsx<ThemeProvider>. Lift Ant DesignConfigProvidertheme logic to entry level;darkAlgorithm/defaultAlgorithmswitching and dark-mode token overrides apply globally for the whole app.Design Decisions
React Context instead of Redux
The codebase already adopts React Context for i18n (
LangContext) and Zustand for authentication & cluster state. Theme state is presentation-layer UI state and mainly consumed inside layout components. React Context keeps consistent architecture with internationalization module, avoiding heavy state library dependency for a single boolean flag.localStorage persistence
User selected theme will survive page refresh. Storage key:
rocketmq-studio-theme.System color scheme fallback
For first-time visitors without saved preference, automatically detect OS appearance via
window.matchMedia('(prefers-color-scheme: dark)').Global root ConfigProvider
Moving theme algorithm switching out of
MainLayoutguarantees all Ant Design components (including standalone modals created byReactDOM.createRootoutside layout tree) correctly render dark style.Hook API Usage