Skip to content

ThemeEditor does not respond to external dark/light mode changes via ConfigProvider #222

@suryatejaKONDLA

Description

@suryatejaKONDLA

Description

When using ThemeEditor wrapped in a ConfigProvider with dynamic algorithm (switching between theme.darkAlgorithm and theme.defaultAlgorithm), the editor's internal UI (left panel with Color, Size, Style tabs) does not update to reflect the theme change. The change only takes effect after a full page refresh.

Environment

  • antd-token-previewer version: 3.0.0
  • antd version: 6.1.4
  • React version: 19.2.3

Steps to Reproduce

  1. Wrap ThemeEditor in a ConfigProvider with dynamic algorithm based on external dark mode state
  2. Toggle the external dark/light mode state
  3. Observe that the editor's internal UI does not update

Code Example

import React from "react";
import { ConfigProvider, theme } from "antd";
import ThemeEditor from "antd-token-previewer/es/ThemeEditor";

function MyThemeEditor() {
    const [isDarkMode, setIsDarkMode] = React.useState(false);
    const [editorTheme, setEditorTheme] = React.useState({
        name: "Custom Theme",
        key: "my-theme",
        config: {
            token: {},
            algorithm: theme.defaultAlgorithm,
        },
    });

    // Update editor theme when dark mode changes
    React.useEffect(() => {
        setEditorTheme((prev) => ({
            ...prev,
            config: {
                ...prev.config,
                algorithm: isDarkMode ? theme.darkAlgorithm : theme.defaultAlgorithm,
            },
        }));
    }, [isDarkMode]);

    return (
        <div>
            <button onClick={() => setIsDarkMode(!isDarkMode)}>
                Toggle Dark Mode (Current: {isDarkMode ? "Dark" : "Light"})
            </button>
            
            <ConfigProvider
                theme={{
                    hashed: true,
                    algorithm: isDarkMode ? theme.darkAlgorithm : theme.defaultAlgorithm,
                }}
            >
                <ThemeEditor
                    key={isDarkMode ? "dark" : "light"}
                    theme={editorTheme}
                    darkAlgorithm={theme.darkAlgorithm}
                    onThemeChange={setEditorTheme}
                />
            </ConfigProvider>
        </div>
    );
}

Expected Behavior

When toggling dark mode externally:

  1. The ConfigProvider's algorithm changes
  2. The ThemeEditor's internal UI (panel backgrounds, text colors, etc.) should update to match the new theme
  3. The theme prop's algorithm is also updated

Actual Behavior

  • The ThemeEditor's internal UI remains in the previous theme state
  • Only a full page refresh causes the UI to update
  • The internal makeStyle hooks appear to cache styles and don't respond to the ConfigProvider algorithm change

Attempted Solutions

  1. ✅ Wrapped with ConfigProvider with hashed: true and dynamic algorithm - Did not work
  2. ✅ Added key prop to force remount - Did not work
  3. ✅ Passed darkAlgorithm prop - Did not work
  4. ✅ Manually unmounting/remounting with state and setTimeout - Did not work
  5. ✅ Updated the theme prop's config.algorithm via useEffect - Did not work

Analysis

Looking at the source code:

  • The makeStyle utility in src/utils/makeStyle.tsx uses antdTheme.useToken() for styling
  • The internal useControlledTheme hook and switchAlgorithm function handle the internal Light/Dark segmented control
  • It appears the internal styles are cached and don't invalidate when the external ConfigProvider context changes

Possible Solutions

  1. Add a prop like externalDarkMode that the component respects
  2. Ensure makeStyle properly responds to ConfigProvider algorithm changes
  3. Expose a method to programmatically trigger the internal switchAlgorithm function

Related

The official demo in docs/examples/theme-editor-simple.tsx shows a similar pattern with ConfigProvider, but the demo controls dark mode via the editor's internal segmented control, not externally.


Thank you for your work on this excellent library! 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions