Dynamically changing Less variables in React Gatsby app with Ant Design at runtime

We are building a White Label platform using React, GatsbyJs and Ant Design. We are … Read more Dynamically changing Less variables in React Gatsby app with Ant Design at runtime

We are building a White Label platform using React, GatsbyJs and Ant Design. We are stuck with Gatsby and Ant Design because we are migrating from an existing system and changing any of those would bring huge impact. Also, we must have a single deploy. Having a build for each White Label is not an option.

So, we need to be able to change style (mainly color) at runtime.

The problem is: Ant Design uses less variables to define it’s themes and we’re not able to change them at runtime, not even with less’s modifyVars.

The thing is we MUST change less variables, and not global CSS or use other means

Ant Design derivates the main variables many times to get adjacent properties. So, for instance, if we define @primary-color as red, when we add a Button to the screen, Ant Design also defines it’s border color, hover color, and many other details with different shades of red.

This means that, if we were to use other styling tool, we would need to generate those color derivations and replace every little property for every component. This would be chaos.

Scenario

We are using gatsby-plugin-antd and gatsby-plugin-less to load less and change vars at build time. Our gatsby-config.js looks like this:

module.exports = {
  siteMetadata: {
    siteUrl: 'https://www.yourdomain.tld',
    title: 'yourtitle'
  },
  plugins: [
    'gatsby-plugin-root-import',
    'gatsby-plugin-typescript',
    {
      resolve: 'gatsby-plugin-antd',
      options: {
        style: true
      }
    },
    {
      resolve: 'gatsby-plugin-less',
      options: {
        lessOptions: {
          javascriptEnabled: true,
          modifyVars: {
            'primary-color': '#FFFFFF',
            'link-color': '#000000',
            'success-color': '#FFFFFF',
            'warning-color': '#000000'
          }
        }
      }
    }
  ]
};

We import styling in our gatsby-browser.js file:

import './src/styles/index';

Our styles/index has:

import 'tachyons';
import './global.css';
import './antd.less';

antd.less:

@import '~antd/dist/antd.less';

And global.css has some general CSS for the project.

It’s working fine with the defined variables at build time.

What we attempted so far…

We have tried out this plugin:
https://github.com/mzohaibqc/antd-theme-webpack-plugin
Which supposedly does exactly what we need. But there’s no example using Gatsby.

We then tried to add the plugin using the gatsby-node.js as mentioned here:
https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/

First, we tried using index.html as the indexFileName for the pluggin. It just doesn’t work.

Then, following the plugin docs, we tried using indexFileName as false and importing the following scripts using Helmet at our pages/index.tsx:

<script> window.less = { async: false, env: 'production' }; 
</script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script> ```

Also didn’t work. If we define indexFileName as false, we get memory over the heap.
If we keep indexFileName as ‘index.html’ and just add the scripts, we are able to call window.less.modifyVars and it returns successfully (we are logging the Promise’s then and error) but it doesn’t affect antd’s variables.

We then tried doing something similar, but instead of loading less externally, we installed it as a node_module and imported it to the file and used it directly in a similar fashion. Got the same result: modifyVars runs and returns successfully but doesn’t affect antd.

Then, we tried something a bit different: we removed gatsby plugins and tried importing less from antd directly, as suggested here:
https://ant.design/docs/react/customize-theme
So we imported it like this:

@import '~antd/lib/style/themes/default.less';
@import '~antd/dist/antd.less';
@import 'your-theme-file.less';

Also, no good. It’s different from the previous scenario, because style gets updated after you save your code. No need to stop Gatsby, as the first solutions. But, modifyVars still has no affect on antd components.

Then, to isolate the issue, we tried to style a basic HTML component – a button – to check if the issue was with gatsby or antd. And… still no success. less.modifyVars didn’t work to change a basic button style on runtime.

So, we think it’s probably something between Gatsby and Less. We checked gatsby-plugin-antd and gatsby-plugin-less to see if we could find something, but found nothing useful.

We assume that the "less instance" or "less context" used by gatsby’s less-loader during build time is not the same we are calling modifyVars on. So it doesn’t affect the original vars.

Totally stuck. Please, help!

Source: React – Stack Overflow


Categories: NewsTags: , , ,

Tags: , , ,


Leave a Reply

Your email address will not be published. Required fields are marked *