Configuring Tailwind CSS for Storybook in an Angular Library inside an NX monorepo
Tags: nx, webdev, angular, storybook
Published: 2024-02-13 17:01:15

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:

```scss
@tailwind base;
@tailwind components;
@tailwind utilities;
```

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:
```ts
// .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
```
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](https://stackoverflow.com/questions/71073685/setting-storybook-scss-import-paths-for-angular-library) 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](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console), 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3y5bw3exdu1tb04v64aw.png)



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:

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

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](https://bio.link/codewithahsan).