DEV Community

Cover image for Configuring Tailwind CSS for Storybook in an Angular Library inside an NX monorepo
Muhammad Ahsan Ayaz
Muhammad Ahsan Ayaz

Posted on

Configuring Tailwind CSS for Storybook in an Angular Library inside an NX monorepo

Well, the title says it all. I spent hours and hours searching how to make this possible and I can't count how many variations of this very title I had searched but could not find a resource that could lead me to the solution. Or I was too stupid to see it. Or I just needed more coffee.
Regardless, here's what happened...

Background

I was working on the task to create a monorepo that has our UI components library which other projects in the same monorepo can use later.

Challenge

The challenge was shipping the component libraries with tailwind css. Now, one way would be to ship the components with the tailwind css styles compiled to inline-styles on the HTML elements. This is so that if the consumer app uses tailwind css or not, they still get all the component styles. This requires a significant amount of configuration and Webpack magic. And the other way (which I chose) was to style the library with tailwind styles, but leaving the tailwind configuration for consumer apps (including storybook being one of the consumers). For example, I created a file storybook.scss inside the .storybook folder created by NX inside my library having the following code:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

With this approach, the consumers can install Tailwind CSS and can include the @tailwind directives while the components will come with the styles automagically. And so can my storybook.

The main challenge

The actual challenge though, was making the styles work with storybook. Now, on the internet, you either find that you should load the .scss (global styles) file inside the .storybook/preview.ts file. But that requires special configuration and extending the Webpack configuration (which I tried and failed at).

For example:

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/angular';

const config: StorybookConfig = {
  stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-styling-webpack', // 👈🏽 This part
      options: {
        rules: [
          {
            test: /^globals\.scss$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: { importLoaders: 1 },
              },
              {
                loader: 'postcss-loader',
                options: { implementation: require.resolve('postcss') },
              },
            ],
          },
        ],
      },
    },
  ],
  framework: {
    name: '@storybook/angular',
    options: {},
  },
};

export default config;

// To customize your webpack configuration you can use the webpackFinal field.
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
// and https://nx.dev/recipes/storybook/custom-builder-configs
Enter fullscreen mode Exit fullscreen mode

And it didn't work, of course. I not only tried this, but a bunch of variations such as finding the existing .scss rules in the webpack configuration programmatically on run-time and adding a rule appropriately but it would always mess something else up.

Another suggested solution on Stack Overflow included working with angular.json, which in my case was project.json inside the NX monorepo. However, using a similar configuration object only made it worse. Because I'm not dealing with an app here that would require browserTarget etc, I'm working with an Angular library which needs to work with storybook. And that storybook needs the global styles for parsing the @tailwind directives.

Anyhow, nothing worked so far.

Solution

Thanks to the NX Console extension for VSCode, I was able to play around the different targets I had in the monorepo and see the default configuration of the storybook. As there was no configuration in my project.json for the library, I was super confused as what do I need to configure. But more than that... "where the heck is storybook configured for this library???". Because there's nothing in the project.json as mylib:storybook. And the extension helped there.

NX Console Screenshot

And then thought, Aha! Can I add some configuration to it? And then I tried a few things, but all I needed to do, was to add the following in my-lib/project.json file:

/* project.json */
{
  ...,
  "targets" {
    "build": {
      ...
    },
    "storybook": {
      "options": {
        "styles": [
          "libs/my-lib/.storybook/styles.scss"
        ]
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Yeah, that! That tiny little configuration object that extends the NX default configurations for storybook and just adds one little style.scss file there, which is using the @tailwind directives.

Note: My library does not ship tailwind styles to storybook. Storybook includes the tailwind styles in the preprocessors and thus my components come alive!

Thank me later

If you found this helpful at all, give this a reaction and follow me on socials.

Top comments (0)