Search code examples
cssreactjsstorybookcss-modules

issue loading css module classes in storybook v6.4


I'm having trouble getting storybook to play nice with css modules within my Gatsby project. I'm able to render the button component but it does not add any of my styling. On inspection of the element, I'm only getting undefined undefined from the following code.

button.jsx

import React from "react"
import * as css from "./style.module.css"

const Button = ({ variant = "button", type, value = null }) => {
  const baseOfVariant = () => {
    if (variant === "input") {
      return (
        <input
          type={type}
          value={value}
          className={`${css.button} ${css.clear_button}`}
        />
      )
    }
    return (
      <button type={type} className={`${css.button} ${css.submit_button}`}>
        {value}
      </button>
    )
  }
  return baseOfVariant()
}

export default Button

button.stories.jsx

import React from "react"
import Button from "./button"

export default {
  title: "Button",
  component: Button,
}

export const Template = args => <Button {...args} />

export const ButtonRegular = Template.bind({})
ButtonRegular.args = {
  variant: "button",
  value: "Click Me",
  type: "submit",
}

main.js

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
  core: {
    builder: "webpack5",
  },
}

Storybook stuff in my devDeps

"devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/polyfill": "^7.12.1",
    "@storybook/addon-actions": "^6.4.0-alpha.2",
    "@storybook/addon-essentials": "^6.4.0-alpha.2",
    "@storybook/addon-links": "^6.4.0-alpha.2",
    "@storybook/addon-viewport": "^6.4.0-alpha.2",
    "@storybook/builder-webpack5": "^6.4.0-alpha.2",
    "@storybook/manager-webpack5": "^6.4.0-alpha.2",
    "@storybook/react": "^6.4.0-alpha.2",
    "babel-loader": "^8.2.2",
    "prettier": "2.2.1",
    "resize-observer-polyfill": "^1.5.1"
  }

Solution

  • Gatsby needs to import css modules with the following synthax:

    import * as css from "./style.module.css"
    

    Where Storybook recognizes only this synthax:

    import css from "./style.module.css"
    

    This is due to the fact that Gatsby and Storybook don't use the same import convention. Fortunately, you can configure Storybook css module import mechanism via .storybook/main.js file.

    const path = require("path")
    
    module.exports = {
      // You will want to change this to wherever your Stories will live
      stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
      addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
      core: {
        builder: "webpack5",
      },
      webpackFinal: async config => {
        // Prevent webpack from using Storybook CSS rules to process CSS modules
        config.module.rules.find(
          rule => rule.test.toString() === "/\\.css$/"
        ).exclude = /\.module\.css$/
    
        // Tell webpack what to do with CSS modules
        config.module.rules.push({
          test: /\.module\.css$/,
          include: path.resolve(__dirname, "../src"),
          use: [
            {
              loader: "style-loader",
              options: {
                modules: {
                  namedExport: true,
                },
              },
            },
            {
              loader: "css-loader",
              options: {
                importLoaders: 1,
                modules: {
                  namedExport: true,
                },
              },
            },
          ],
        })
        // Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
        config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
        // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
        config.module.rules[0].use[0].options.plugins.push(
          require.resolve("babel-plugin-remove-graphql-queries")
        )
        return config
      },
    }
    

    With the above configuration, Storybook now accept this import synthax and button.jsx is correctly styled.

    import * as css from "./style.module.css"