storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.93k stars 9.21k forks source link

How do I include global styles (scss) once for all Storybook iframes? #6364

Closed omaracrystal closed 5 years ago

omaracrystal commented 5 years ago

Describe the bug I have been trying multiple ways of incorporating global styles (scss) once for all Storybook Iframes and have been unsuccessful. There doesn't seem to be a clear concise way to do this.

To Reproduce Attempts:

    • Import the global styles within each component.
    • Results: Styles are applied, but, multiple global.scss styles is repeated {story#} x times.
    • One place recommend creating a decorator for Storybook and apply the "global" css that way.
    • Result: would not work for what I'm trying to do (multiple styles, mixins, variables, etc) This only works for small CSS changes
    • In config under .storybook require('../libs/storybook/global-styles.scss'); within the loadStories function
    • Result: Nothing
    • Tried importing the global styles within the Storybook index.ts
    • Result: Nothing
    • Tried adding the global styles via angular.json file
      • Result: Nothing

Expected behavior I would expect to be able to import Global (scss) files in one place so that can be applied to every Story's Iframe. Could there be a config setting I'm not aware of?

System:

Additional context I am hoping that I am missing some configuration within storybook that would make this simple to resolve.

kroeder commented 5 years ago

Try adding your global.scss File into angular.json

Check your defaultProject (there's a defaultProject property inside the json) and add it to the styles list

"styles": [
              "projects/your-cli-project/src/lib/styles/your-styles.scss"
            ],

I do it that way and it works just fine. Is that an option for you?

stale[bot] commented 5 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

blemaire commented 5 years ago

Hi @omaracrystal here is how I did it: in the .storybook/config.jsfiles, add the import with the correct loaders inlined:

import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

Then add/import all the styles you need in the scss-loader.scss file:

$font-path: '../projects/lib/src/theming/fonts/OpenSans/';

@import '../projects/lib/src/theming/reset.scss';
@import '../projects/lib/src/theming/main.scss';

html {
  font-family: $font-name;
  font-size: $font-size--small;
}

The solution proposed by @kroeder works as long as your using components from an Angular application but for libraries, you cannot add the styles property in the angular.json file

yashsway commented 5 years ago

Try adding your global.scss File into angular.json

Check your defaultProject (there's a defaultProject property inside the json) and add it to the styles list

"styles": [
              "projects/your-cli-project/src/lib/styles/your-styles.scss"
            ],

I do it that way and it works just fine. Is that an option for you?

I did this exact thing, but it doesn't seem to load this for me when I run storybook

stale[bot] commented 5 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

stale[bot] commented 5 years ago

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

ozanmanav commented 4 years ago

Hi @omaracrystal here is how I did it: in the .storybook/config.jsfiles, add the import with the correct loaders inlined:

import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

Then add/import all the styles you need in the scss-loader.scss file:

$font-path: '../projects/lib/src/theming/fonts/OpenSans/';

@import '../projects/lib/src/theming/reset.scss';
@import '../projects/lib/src/theming/main.scss';

html {
  font-family: $font-name;
  font-size: $font-size--small;
}

The solution proposed by @kroeder works as long as your using components from an Angular application but for libraries, you cannot add the styles property in the angular.json file

Is that working for everyone ? Not working my side :(

orlov-vo commented 4 years ago

@ozanmanav did you try import it in .storybook/config.js?

PS: because for me it works but I import just .css file without webpack-loaders

garrettmaring commented 4 years ago

This seems to no longer work using the main.js file structure of Storybook v5.3

shilman commented 4 years ago

@garrettmaring did you try with .storybook/preview.js rather than .storybook/config.js?

ycadaner-merkos302 commented 4 years ago

@garrettmaring I finally got it working for .css files using import '!style-loader!css-loader!./main.css'. At first I tried toying with the webpack config, but I removed all my custom rules, and inlined it like above. Obviously npm install the loaders.

garrettmaring commented 4 years ago

@shilman yes, that did it 👍 Pretty clear once I saw some documentation on it. There might be some room for clearer docs in the main Storybook documentation. I found this article to be clear.

shilman commented 4 years ago

@garrettmaring Mind submitting a PR to help improve the docs?

impurity-dev commented 4 years ago

@garrettmaring I finally got it working for .css files using import '!style-loader!css-loader!./main.css'. At first I tried toying with the webpack config, but I removed all my custom rules, and inlined it like above. Obviously npm install the loaders.

Just some FYI that i just figured out, this approach works wonders when serving storybook locally, but it does not work (from what I saw) with build-storybook.

My solution Add <link rel="stylesheet" href="./your-global-styles.css" /> to the preview-head.html. Then use the -s flag on your-global-styles.css's directory copy the styles to the build directory of storybook. Now the iframe.html "should" be referencing your-global-styles.css from the same directory.

Only issue with this is when running locally, the browser console will say it cannot find localhost/your-global-styles.css but it still works as intended.

If anyone has a better way of approaching this, or knows of a proper solution, let me know :)

blemaire commented 4 years ago

we serve scss files in storybook using the following:

import '!style-loader!css-loader!sass-loader!./main.scss';

This works fine for us

lopis commented 4 years ago

@blemaire Where are you using that line?

4ndv commented 4 years ago

@blemaire Where are you using that line?

@lopis just create preview.js in the .storybook folder and put that line into it

llmartinll commented 4 years ago

Thanks everyone. Confirming that

works for us; storybook i.c.w. an Angular 9 library (so no option to add it to the angular.json file)

vdanchenkov commented 4 years ago

In nextjs based setup simple line of import "../styles/main.css"; (as in main app) to .storybook/preview.js adds styles correctly.

thomasdavis commented 4 years ago

The above solutions works if all your pathing is relative ../../src/main.scss but my current project uses SCSS global/alias.

My main.js webpack config for Storybook can compile the alias. But when I try import global/alias SCSS into my preview.js then it can't resolve the paths.

Not sure where to go.

caseytrombley commented 4 years ago
import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

I tried this, but getting error. I need Storybook to know about my global css variables and mixins.

ERR! import '!style-loader!css-loader!sass-loader!./scss-loader.scss';
ERR!        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ERR! 
ERR! SyntaxError: Unexpected string
caseytrombley commented 4 years ago

In nextjs based setup simple line of import "../styles/main.css"; (as in main app) to .storybook/preview.js adds styles correctly.

Does this styles/main.css contain your global SCSS variables? Do they get applied in Storybook at all? I tried this, but still get SassError: Undefined variable: $my-variable-here

caseytrombley commented 4 years ago

Hi @omaracrystal here is how I did it: in the .storybook/config.jsfiles, add the import with the correct loaders inlined:

import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

Then add/import all the styles you need in the scss-loader.scss file:

$font-path: '../projects/lib/src/theming/fonts/OpenSans/';

@import '../projects/lib/src/theming/reset.scss';
@import '../projects/lib/src/theming/main.scss';

html {
  font-family: $font-name;
  font-size: $font-size--small;
}

The solution proposed by @kroeder works as long as your using components from an Angular application but for libraries, you cannot add the styles property in the angular.json file

Is that working for everyone ? Not working my side :(

Nope. Doesn't help me either. I get this error now:

ERR! import '!style-loader!css-loader!sass-loader!./scss-loader.scss';
ERR!        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ERR! 
ERR! SyntaxError: Unexpected string
caseytrombley commented 4 years ago

Describe the bug I have been trying multiple ways of incorporating global styles (scss) once for all Storybook Iframes and have been unsuccessful. There doesn't seem to be a clear concise way to do this.

To Reproduce Attempts:

    • Import the global styles within each component.
    • Results: Styles are applied, but, multiple global.scss styles is repeated {story#} x times.
    • One place recommend creating a decorator for Storybook and apply the "global" css that way.
    • Result: would not work for what I'm trying to do (multiple styles, mixins, variables, etc) This only works for small CSS changes
    • In config under .storybook require('../libs/storybook/global-styles.scss'); within the loadStories function
    • Result: Nothing
    • Tried importing the global styles within the Storybook index.ts
    • Result: Nothing
    • Tried adding the global styles via angular.json file

      • Result: Nothing

Expected behavior I would expect to be able to import Global (scss) files in one place so that can be applied to every Story's Iframe. Could there be a config setting I'm not aware of?

System:

  • OS: MacOS
  • Device: Macbook Pro 2015
  • Browser: Chrome
  • Framework: Angular
  • Addons: - [addon-centered, addon-viewport, addon-info]
  • Version: [^5.0.1]

Additional context I am hoping that I am missing some configuration within storybook that would make this simple to resolve.

Did you ever get this resolved? If so, what was the solution? Thanks!

impurity-dev commented 4 years ago

@caseytrombley The solution is to add import '!style-loader!css-loader!sass-loader!./styles.scss'; to your preview.js.

FullstackJack commented 4 years ago

For Create React App + Storybook, I added the following to config.js to get my CSS Reset applied to Storybook.

import '!style-loader!css-loader!../src/reset.css';

blowsie commented 4 years ago

Anyone have a solution working for postcss-scss?

nirus commented 4 years ago

You can read the blog that i wrote that exactly speaks about implementing SCSS constants for your storybook via custom webpack config.

There is defect that i have logged explaining current config bug https://github.com/storybookjs/storybook/issues/11052 and blog that i wrote as a work around.

Hope this helps!

corysimmons commented 4 years ago

For installs that have main.js (i.e. you ran npx -p @storybook/cli sb init in a CreateReactApp project), just add preview.js as a sibling then do this:

// .storybook/preview.js
require('!style-loader!css-loader!../src/css/tailwind-utility-classes.css')

If it complains one of those loaders isn't installed (they should be if it's a CRA project), just manually install them (i.e. yarn add style-loader css-loader).

Lock thread so people can just jump to bottom for solution when the upvoted/deprecated solution fails?

dcts commented 4 years ago

@garrettmaring did you try with .storybook/preview.js rather than .storybook/config.js?

When I create a styles.css file inside the same directory and import it with import './styles.css'; inside my preview.js file, my storybook suddenly just is stuck in a loading state... :(

Any idea how to resolve that?

I use storybook with the open-wc config for webcomponents and have a preview.js and a main.js file inside my .storybook folder.

garrettmaring commented 4 years ago

@dcts that could be because your ./styles.css is referencing Tailwind utilities, using some features that need to be pre-processed, or in some other way "broken" as a standalone file.

I needed to do three things:

  1. Create an input css file. For me, this is css/tailwind.css where I import anything needed for my Tailwind setup.
  2. When running storybook, build that file first. For me, this was a PostCSS command postcss css/tailwind.css -o css/index.css
  3. In .storybook/preview.js (create that file if needed) add import '../css/index.css

I am using Twin and I can use this component as expected:

import tw, { styled } from 'twin.macro'

const StyledReactionButton = styled.button`
  ${tw`bg-blue-400 bg-opacity-25`}
`

I think a better solution would be to edit the storybook webpack config to handle the postcss step.

od-nikola-mitic commented 4 years ago

I am using Vue.js with scss. My issue is that when importing global scss in preview.js my chrome devtolls is super slow and not useable. Anyone having the same issue? Any alternatives? I am trying not to import global scss in each of the my stories.

hayatbiralem commented 3 years ago

The above solutions worked in a way, but this method from official docs eliminates the problem in the whole project.

In short, we need to extend Webpack configuration to set scss loaders.

Sample code from official docs

// .storybook/main.js

const path = require('path');

// Export a function. Accept the base config as the only param.
module.exports = {
  webpackFinal: async (config, { configType }) => {
    // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.

    // Make whatever fine-grained changes you need
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });

    // Return the altered config
    return config;
  },
};

Usage

Now you can import scss files as aways in .storybook/preview.js:

// .storybook/preview.js

import "../src/styles/main.scss";

// ...

...and even in your components too:

<!-- src/components/MyComponent.vue -->

<template>
  ...
</template>

<script>
// ...
</script>

<style lang="scss">
@import "../styles/components/components.my-component";
</style>
ProTip commented 3 years ago

I ran into an issue where importing a sizable SCSS project from preview.js is causing 5+ second recompile times on any change to anything in the project. Moving this out into a story somehow gets everything back down to <1s recompile times..

jtonneyck commented 3 years ago

I am using Storybook with Gatsby and the standard scss presets. After importing the global.scss file to preview.js the styles are picked up, but if I define variables in global.scss and use them in a component the following error is triggered:

ERROR in ./src/stories/button.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/stories/button.scss)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Undefined variable: "$black".

I'm suspecting that the global.scss file gets loaded in too late, but I don't know how to configure it correctly. Maybe it's even a bug, because adding global styles to preview.js is the recommended method.

Update

It's not the order. If I write the following in global.scss.

body {
    background-color: black;
}

and the following in Button.scss:

body {
  background-color:green;
}

The background color is in fact green. This means Buttons.scss is loaded after Global.scss like it should, but the variables are still not picked up.

Solution Yeez, I learned a lot today. The main problem was that sass variables are only defined in the file they are declared in by default. If you want to use variables across files, you have to use sass-modules. The old way was to use @import, but the new preferred way is @use. I start every module like button.scss with @use pathtomodule/global.scss. In my case this makes the import in preview.js redundant.

There was another catch. @use is currently only supported by dart sass. I had node-sass installed (npm i node-sass --save-dev). There is a package called dart-sass (npm i dart-sass --save-dev), but that is not the correct one for the before mentioned presets. Dart sass has become regular sass. You can simply install it with npm i sass --save-dev.

hayatbiralem commented 3 years ago

Hi @Piepongwong,

I'm not using Gatsby but in Vue I solved that problem putting all mixin and variable imports into one file named _common.scss and import it in components like this:

<style lang="scss">
@import 'path/to/styles/_common.scss';
@import 'path/to/styles/components/_components.component.scss';
</style>

In this way I'm always sure that my mixins and variables exists but be aware of that you need to abstract all your components and variables correctly. You could look at inuitcss for best practices.

Hope this helps.

tzs007 commented 3 years ago

Hi @omaracrystal here is how I did it: in the .storybook/config.jsfiles, add the import with the correct loaders inlined:

import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

Then add/import all the styles you need in the scss-loader.scss file:

$font-path: '../projects/lib/src/theming/fonts/OpenSans/';

@import '../projects/lib/src/theming/reset.scss';
@import '../projects/lib/src/theming/main.scss';

html {
  font-family: $font-name;
  font-size: $font-size--small;
}

The solution proposed by @kroeder works as long as your using components from an Angular application but for libraries, you cannot add the styles property in the angular.json file

Is that working for everyone ? Not working my side :(

not for me:( i tried with next.js and reactstrap but it didnt load the app.scss from my style folder :/

thefill commented 3 years ago

Hi @omaracrystal here is how I did it: in the .storybook/config.jsfiles, add the import with the correct loaders inlined:

import '!style-loader!css-loader!sass-loader!./scss-loader.scss';

Then add/import all the styles you need in the scss-loader.scss file:

$font-path: '../projects/lib/src/theming/fonts/OpenSans/';

@import '../projects/lib/src/theming/reset.scss';
@import '../projects/lib/src/theming/main.scss';

html {
  font-family: $font-name;
  font-size: $font-size--small;
}

The solution proposed by @kroeder works as long as your using components from an Angular application but for libraries, you cannot add the styles property in the angular.json file

Is that working for everyone ? Not working my side :(

not for me:( i tried with next.js and reactstrap but it didnt load the app.scss from my style folder :/

Try @hayatbiralem way - it should work.

jimsheen commented 3 years ago

This worked for me in latest version of storybook @storybook/react@6.1.10 Hope this helps someone!

// .storybook/main.js
const path = require('path');

module.exports = {
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)",
    "../app/frontend/components/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    '@storybook/preset-scss'
  ],
  webpackFinal: async (config) => {
    // this sets the default path for modules
    config.resolve.modules = [
      ...(config.resolve.modules || []),
      path.resolve(__dirname, "../app/frontend"),
    ];

    config.module.rules.map(rule => {
      if (rule.test instanceof RegExp && rule.test.toString() === '/\\.s[ca]ss$/') {
        rule.use.push({
          loader: require.resolve('sass-resources-loader'),
          options: {
            resources: [
              path.resolve(__dirname, '../app/frontend/styles/base/_variables.scss')
            ]
          }
        })
      }
      return rule
    })
    return config;
  },
}
smithki commented 3 years ago

@garrettmaring I finally got it working for .css files using import '!style-loader!css-loader!./main.css'. At first I tried toying with the webpack config, but I removed all my custom rules, and inlined it like above. Obviously npm install the loaders.

Just some FYI that i just figured out, this approach works wonders when serving storybook locally, but it does not work (from what I saw) with build-storybook.

My solution Add <link rel="stylesheet" href="./your-global-styles.css" /> to the preview-head.html. Then use the -s flag on your-global-styles.css's directory copy the styles to the build directory of storybook. Now the iframe.html "should" be referencing your-global-styles.css from the same directory.

Only issue with this is when running locally, the browser console will say it cannot find localhost/your-global-styles.css but it still works as intended.

If anyone has a better way of approaching this, or knows of a proper solution, let me know :)

I'm also having this issue where global styles imported into preview.js work with start-storybook but not build-storybook. I can't use this preview-head.html workaround because I need to process the global CSS through less-loader. Is there another workaround or is this a bug in storybook?

martiiian commented 3 years ago

It's works for me, to solve problem with common scss variables, functions. Tested with nuxt, with using @nuxtjs/style-resources module

  webpackFinal(config, { configType }) {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader', {
        loader: require.resolve('sass-resources-loader'),
        options: {
          // core.scss contains variables, functions, mixins..
          resources: path.resolve(__dirname, '../assets/styles/core.scss')
        }
      }],
      include: path.resolve(__dirname, '../'),
    })

    return config
  }
jennybehan commented 3 years ago

My style files are only in src/styles/components, src/styles/base, src/styles/variable directories, and had root style file importing all those modules in src/styles/main.scss like this.

src
  /styles
    /components
    /base
    /variables
  // ...
  main.scss

Frist I added common variable and base files in main.js webpackFinal config like below,

// main.js
// ...
const sassLoaderRule = {
    test: /\.s[ac]ss$/i,
    use: [
        {
            loader: 'sass-loader',
            options: {
                additionalData: `
                    @import "@style/variables/all.scss";  // I also configured alias `@style`
                    @import '@style/base/all.scss';
                `
            }
        }
    ]
};

config.module.rules.push(sassLoaderRule);
return config;
//... 

Then, in the preview.js file, you should import root style files to apply whole style.

// preview.js
import '../src/style/main.scss';
import '@style/main.scss';
karmasalad commented 3 years ago

@smithki I'm also having this issue where global styles imported into preview.js work with start-storybook but not build-storybook. I can't use this preview-head.html workaround because I need to process the global CSS through less-loader. Is there another workaround or is this a bug in storybook?

Were you able to find a workaround for this, @smithki? I'm also running into the same issue where I'm missing my global styles when running build-storybook.

cuznerdexter commented 3 years ago

Anyone have global scss styles working with Storybook & NX workspaces & Angular Libraries ?

@nirus I tried your guide on your blog but it is not working for me. I have tried both with and without your code - same result.

I try and run an individual Library eg: nx run my-lib:storybook

Storybook loads and looks correct in the first story, but the next story I select ignores the styles. eg: ButtonComponent template: <button mat-raised-button color="primary">Primary</button>

// this looks as expected
export const primary = () => ({
  component: ButtonComponent,
  props: {
  }
})

// this look wrong
export const accent = () => ({
  component: ButtonComponent,
  template: `<button mat-raised-button color="accent">Accent</button>`,
  props: {
  }
})

// this look wrong
export const warn = () => ({
  component: ButtonComponent,
  template: `<button mat-raised-button color="warn">Warn</button>`,
  props: {
  }
})

Here are some of my files: Main Storybook webpack.config.js:

module.exports = async ({ config, mode }) => {
  // Return the altered config
  return config;
};

Lib Files: Config.js: (auto created in NX)

import { configure, addDecorator } from '@storybook/angular';
import { withKnobs } from '@storybook/addon-knobs';

addDecorator(withKnobs);
configure(require.context('../src/lib', true, /\.stories\.(j|t)sx?$/), module);

webpack.config.js: (auto created in NX)

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const rootWebpackConfig = require('../../../../.storybook/webpack.config');
/**
 * Export a function. Accept the base config as the only param.
 *
 * @param {Parameters<typeof rootWebpackConfig>[0]} options
 */
module.exports = async ({ config, mode }) => {
  config = await rootWebpackConfig({ config, mode });

  const tsPaths = new TsconfigPathsPlugin({
    configFile: './tsconfig.base.json',
   });

  config.resolve.plugins
    ? config.resolve.plugins.push(tsPaths)
    : (config.resolve.plugins = [tsPaths])

  return config;
};

Angular.json:

"styles": [
              "node_modules/flag-icon-css/css/flag-icon.min.css",
              "apps/main-app/src/styles.scss",
              "node_modules/swiper/swiper.scss"
 ],
trickydisco78 commented 3 years ago

I'\ve added a decorator (withHTMLDOc) to preview.js and now it's broken the loading of css. How do i get the css to load along with this addon?

import { addDecorator } from '@storybook/html';
import { withHTMLDOC } from 'storybook-addon-html-document/html';

import '../src/css/styles.css';

addDecorator(withHTMLDOC);
proxycase commented 3 years ago

I'\ve added a decorator (withHTMLDOc) to preview.js and now it's broken the loading of css. How do i get the css to load along with this addon?

import { addDecorator } from '@storybook/html';
import { withHTMLDOC } from 'storybook-addon-html-document/html';

import '../src/css/styles.css';

addDecorator(withHTMLDOC);

I found that mine didn't work with importing it there, so I loaded mine in the data options of css-loader in my main.js as shown below. To be fair, I am using sass, but the concept could be the same even for css (maybe you pass it into css-loader instead)

Also my situation uses vue (2.6.6) with nuxt (2.12.2), so I had to add the resolve section, and also make sure my urls in my scss files all were not relative paths "../../assets/images/example.png" and instead uses the webpack (4.43.0) version like so "~/assets/images..."

Hope this helps someone!

const path = require("path");

module.exports = {
  stories: ["../components/**/*.stories.js"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "storybook-addon-pseudo-states",
    "storybook-addon-outline",
  ],
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        "style-loader",
        // Translates CSS into CommonJS
        "css-loader",
        {
          // Compiles Sass to CSS
          loader: "sass-loader",
          options: {
            data: `@import "./assets/scss/app.scss";`,
            includePaths: [__dirname, "./assets/**/*"],
          },
        },
      ],
      resolve: {
        alias: {
          "@": path.resolve(__dirname, "assets"),
          "~": path.resolve(__dirname, "assets"),
        },
      },
    });

    // Return the altered config
    return config;
  },
};
mortalapeman commented 3 years ago

Anyone have global scss styles working with Storybook & NX workspaces & Angular Libraries ?

@nirus I tried your guide on your blog but it is not working for me. I have tried both with and without your code - same result.

I try and run an individual Library eg: nx run my-lib:storybook

Storybook loads and looks correct in the first story, but the next story I select ignores the styles. eg: ButtonComponent template: <button mat-raised-button color="primary">Primary</button>

// this looks as expected
export const primary = () => ({
  component: ButtonComponent,
  props: {
  }
})

// this look wrong
export const accent = () => ({
  component: ButtonComponent,
  template: `<button mat-raised-button color="accent">Accent</button>`,
  props: {
  }
})

// this look wrong
export const warn = () => ({
  component: ButtonComponent,
  template: `<button mat-raised-button color="warn">Warn</button>`,
  props: {
  }
})

Here are some of my files: Main Storybook webpack.config.js:

module.exports = async ({ config, mode }) => {
  // Return the altered config
  return config;
};

Lib Files: Config.js: (auto created in NX)

import { configure, addDecorator } from '@storybook/angular';
import { withKnobs } from '@storybook/addon-knobs';

addDecorator(withKnobs);
configure(require.context('../src/lib', true, /\.stories\.(j|t)sx?$/), module);

webpack.config.js: (auto created in NX)

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const rootWebpackConfig = require('../../../../.storybook/webpack.config');
/**
 * Export a function. Accept the base config as the only param.
 *
 * @param {Parameters<typeof rootWebpackConfig>[0]} options
 */
module.exports = async ({ config, mode }) => {
  config = await rootWebpackConfig({ config, mode });

  const tsPaths = new TsconfigPathsPlugin({
    configFile: './tsconfig.base.json',
   });

  config.resolve.plugins
    ? config.resolve.plugins.push(tsPaths)
    : (config.resolve.plugins = [tsPaths])

  return config;
};

Angular.json:

"styles": [
              "node_modules/flag-icon-css/css/flag-icon.min.css",
              "apps/main-app/src/styles.scss",
              "node_modules/swiper/swiper.scss"
 ],

@cuznerdexter I have the same situation as you. I eventually gave up trying to figure out how to write a rule that will work with the janky configuration that angular has going for storybook and opted to just modify the SCSS rule directly. Add the following to your Nx Library .storybook/webpack.config.js file:

const scssRule = config.module.rules.find(x => String(x.test) === String(/\.scss$|\.sass$/));
const sassLoader = scssRule.use.find(x => x.options && x.options.sassOptions);
sassLoader.options.sassOptions.includePaths = [path.join(__dirname, 'relative/path/to/your/styles`)];

Seems jank, but it gets the job done.

sarangk-hotstar commented 3 years ago

With v6 we can directly import styles in preview.js that will be available globally!

// Global CSS Import that is required across stories
import '../src/styles/base/_typography.css';

import '../src/styles/abstract/_mixins.css';
import '../src/styles/abstract/_utilities.css';

import '../src/styles/theme/_default.css';
Jordaneisenburger commented 3 years ago

I can confirm that in the latest version 6.3 "simply" importing a css files in preview.js does not work.

shilman commented 3 years ago

@Jordaneisenburger Do you a have a reproduction repo you can share? If not, can you create one? See how to create a repro.