I understand how to change my web site theme programmatically or using states with Antd and react, but how do I respect user settings for dark mode, without having to reload the web site for the theme to apply, when browser changes mode automatically based on system settings.
My understanding is that since Antd 5.x moved to cssinjs, I can no longer use theme colors in my css anymore, so @media-query isn't an option, but I might be wrong.
Like what one of the commenters mentioned, add a listener to listen on changes in the system's color scheme. If it changes, then change the darkMode
state so React can re-evaluate and propagate it to the ConfigProvider
.
Be sure to also include another useEffect
to do the initial evaluation for setting darkMode
on initial page load.
Here's a minimum viable example for implementing it:
import React, { useEffect, useState, useCallback } from "react";
import { Button, ConfigProvider, Input, Space, theme } from "antd";
const App: React.FC = () => {
const [darkMode, setDarkMode] = useState(false);
const windowQuery = window.matchMedia("(prefers-color-scheme:dark)");
const darkModeChange = useCallback((event: MediaQueryListEvent) => {
console.log(event.matches ? true : false);
setDarkMode(event.matches ? true : false);
}, []);
useEffect(() => {
windowQuery.addEventListener("change", darkModeChange);
return () => {
windowQuery.removeEventListener("change", darkModeChange);
};
}, [windowQuery, darkModeChange]);
useEffect(() => {
console.log(windowQuery.matches ? true : false);
setDarkMode(windowQuery.matches ? true : false);
}, []);
return (
<ConfigProvider
theme={{
algorithm: darkMode ? theme.darkAlgorithm : theme.compactAlgorithm
}}
>
<Space>
<Input placeholder="Please Input" />
<Button type="primary">Submit</Button>
</Space>
</ConfigProvider>
);
};
export default App;