Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storybook Component-level css file not working

I created a react app using create-react-app, and added a button component, a css for the button. When I load the story for the button, the styles are not loaded for the button. Pasting below, the related files. Is there any configuration that I am to do, to get this up and running with styles?

github repo for the project

Component: index.js

 import React, { Component } from 'react';
import styles from './style.css';
class CustomButton extends Component{
    render(){
        return (
            <button className={styles.customButton}>Hello</button>     
        );
    }
}
export default CustomButton;

style.css:

.customButton {
    border: 1px solid red;
    padding: 10px;
    background-color: rgb(223, 19, 19);
}

Story file:

import React from 'react';
import CustomButton from '../../src/index';
import { storiesOf } from '@storybook/react';


const story = storiesOf("Custom button",module);

story.addWithJSX("simple",() => <CustomButton/>);

System info:

Environment Info:

  System:
    OS: Windows 7 6.1.7601
    CPU: (2) x64 Intel(R) Core(TM) i3-2370M CPU @ 2.40GHz
  Binaries:
    Node: 10.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.9.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 84.0.4147.125
  npmPackages:
    @storybook/addon-info: ^5.3.19 => 5.3.19
    @storybook/components: ^5.3.19 => 5.3.19
    @storybook/preset-create-react-app: ^3.1.4 => 3.1.4
    @storybook/react: ^5.3.19 => 5.3.19
like image 771
Akhil Avatar asked Aug 20 '20 04:08

Akhil


People also ask

How do you add global styles in react?

To apply global CSS styles in a React app, write your css in a file with a . css extension and import it in your index. js file. Global CSS should be imported in index.

What is preview JS in storybook?

storybook/preview. js file. This is loaded in the Canvas tab, the “preview” iframe that renders your components in isolation. Use preview. js for global code (such as CSS imports or JavaScript mocks) that applies to all stories.


2 Answers

In order to storybook works with webpack, you have to firstly create file main.js under the .storybook dir. Then add style-loader + css-loader loaders to resolve your css import. Keep in mind, enable modules: true option in css-loader to help you import your classes:

.storybook\main.js

const path = require('path');

module.exports = {
  webpackFinal: async config => {
    // Remove the existing css rule
    config.module.rules = config.module.rules.filter(
      f => f.test.toString() !== '/\\.css$/'
    );

    config.module.rules.push({
      test: /\.css$/,
      use: ['style-loader', {
        loader: 'css-loader',
        options: {
          modules: true, // Enable modules to help you using className
        }
      }],
      include: path.resolve(__dirname, '../src'),
    });

    return config;
  },
};
like image 148
tmhao2005 Avatar answered Nov 04 '22 00:11

tmhao2005


tmhao2005's answer helps a lot. Note however that this is probably duplicating some Webpack rule config from your main app, and things will potentially get out of sync if you decide to make tweaks or add other CSS loaders in the future. For instance, if you decide to add postcss-loader, you'd need to remember to add it in both your app's Webpack config in webpack.config.js and your Storybook Webpack config in .storybook/main.js (hint: you will not remember!).

Here's a slightly cleaner tweaked version that tells Storybook to reuse your app's Webpack CSS rule config. This version will stay in sync with your main app's Webpack rule:

// .storybook/main.js

// Imports the app's Webpack Config (change this to require() style with older Node.js versions).
import appWebpackConfig from '../webpack.config.js';

const isCSSRule = (rule) => rule.test.toString() === '/\\.css$/';

module.exports = {
    ...
    webpackFinal: (config) => {
        // Removes the existing CSS rule.
        config.module.rules = config.module.rules.filter((rule) => !isCSSRule(rule));

        // Tells Storybook to use the same CSS rule config as our app.
        config.module.rules.push(appWebpackConfig.module.rules.find(isCSSRule));

        return config;
    }
    ...
};

I tested this with Storybook 6.0.21 and it's working pretty nicely.

like image 44
David Calhoun Avatar answered Nov 03 '22 23:11

David Calhoun