FrontyBlog

Ant Design toggling dynamically custom theme

8/2/2020

Hey there who are using ant design, If you wanna add one more theme to your application, this information can be useful. When I faced this task I think that it would be easy solution because antd has a configuration with variables and support it in dynamically should be ease. But I forgot for the .less and live compilation for the product. And as an additional, I'm using a create react app, that hasn't access to the webpack configuration from the box.

Tools

During some research and googling, was find several examples and articles that already solving this problem.

Most common solution that I've met its npm module: https://github.com/mzohaibqc/antd-theme-webpack-plugin

Here is one alternative package: https://www.npmjs.com/package/antd-theme-generator , I haven't tried antd-theme-generator, who wants to try alternative here is a article with example how to configure: https://annacoding.com/article/gVcF6qCZkfnM3JOnPxBqx/Change-Ant-Design-Theme-dynamically-in-React-Create-React-App

And to implement both of these solutions with Create react app we need, add additional webpack configuration module customize-cra.

Solution

Main packages that I'm using:

  1. antd v3 (with v4 works the same)
  2. customize-cra
  3. create-react-app
  4. antd-theme-webpack-plugin

Project Configuration

To our root directory we are adding file config-overrides.js

//config-overrides.js
const path = require("path");
const {
override,
fixBabelImports,
addLessLoader,
addWebpackPlugin,
} = require("customize-cra");
const AntDesignThemePlugin = require("antd-theme-webpack-plugin");
const options = {
stylesDir: path.join(__dirname, "./src/antd-custom-style"),
antDir: path.join(__dirname, "./node_modules/antd"),
varFile: path.join(__dirname, "./src/antd-custom-style/vars.less"),
// list of variables that will be listening
themeVariables: ["@primary-color", "@body-background"],
generateOnce: false, // generate color.less on each compilation
};
module.exports = override(
fixBabelImports("import", {
libraryName: "antd",
libraryDirectory: "es",
style: true,
}),
addWebpackPlugin(new AntDesignThemePlugin(options)),
addLessLoader({
javascriptEnabled: true,
})
);

themeVariables: ['@primary-color', '@body-background'] depends on our example application will be listening just these two variables

You can generate a list of all antd variables and paste it to the themeVariables field, here is code implementation example from antd-theme-webpack-plugin : https://github.com/mzohaibqc/antd-theme-webpack-plugin/blob/ebc9eb92c9ea7cbe3e703470bfc9ede131a7f2cc/examples/customize-cra/config-overrides.js#L21

Main fields that should be configured depending on your project varFile, stylesDir, themeVariables, everything else it's boilerplate.

Add toggler inside the Component

To any of your component add this two button, two trigger theme dynamic

<button
type="button"
onClick={() => {
window.less.modifyVars({
'@primary-color': 'red',
'@body-background': 'yellow',
});
}}
>
Red Theme
</button>
<button
type="button"
onClick={() => {
window.less.modifyVars({
'@primary-color': 'blue',
'@body-background': 'purple',
});
}}
>
Blue Theme
</button>

In multiple sources, I was found examples of where to the /public folder was added color.less, I cannot reproduce this examples, there were some mistakes, I assume it's a pretty old approach.

That's all now you have antd with ability to configure theming dynamically and improve you user experience.

References:

  1. https://github.com/mzohaibqc/antd-theme-webpack-plugin
  2. https://ant.design/docs/react/customize-theme
  3. https://github.com/ant-design/ant-design-pro/blob/56e648ec14bdb9f6724169fd64830447e224ccb1/config/config.js#L45
  4. https://github.com/arackaf/customize-cra
  5. https://medium.com/@mzohaib.qc/ant-design-dynamic-runtime-theme-1f9a1a030ba0
  6. https://github.com/YumcoderCom/antd-them-switch-cra
© 2020 Vitaly Yastremsky