Using TailwindCss in Storybook 6 with Angular

Viewed 1257

I am building a component library with Angular (11.2.8) and I try to add TailwindCss and Storybook 6.

I have found different configuration but none of them work. My components have no style when I run storybook.

Here is my configuration :

.storybook/main.js

const path = require('path');
module.exports = {
  stories: ['../projects/storybook/**/*.stories.ts'],
  addons: [
    '@storybook/addon-actions',
    '@storybook/addon-links',
    '@storybook/addon-knobs',
    '@storybook/addon-viewport',
    '@storybook/addon-docs',
    '@storybook/addon-a11y',
    '@storybook/addon-storysource'
  ],
  webpackFinal: async (config, { configType }) => {

    config.module.rules.push({
      test: /\,css&/,
      use: [
        {
          loader: 'postcss-loader',
          options: {
            ident: 'postcss',
            plugins: [
              require('tailwindcss'),
              require('autoprefixer')
            ]
          }
        },
      ],
      include: path.resolve(__dirname, '../'),
    });

    return config;
  }
};

.storybook/preview.js

import '../src/styles.scss';
import { setCompodocJson } from '@storybook/addon-docs/angular';
import docJson from '../documentation/documentation.json';
setCompodocJson(docJson);

src/styles.scss

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

package.json

{
  "name": "test",
  "version": "0.0.1",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build:prod": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "docs:json": "compodoc -d documentation -p projects/test/tsconfig.lib.json -e json ",
    "storybook": "npm run docs:json && start-storybook -p 6006",
    "build-storybook": "npm run docs:json && build-storybook -o dist/storybook"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.2.7",
    "@angular/common": "~11.2.7",
    "@angular/compiler": "~11.2.7",
    "@angular/core": "~11.2.7",
    "@angular/forms": "~11.2.7",
    "@angular/platform-browser": "~11.2.7",
    "@angular/platform-browser-dynamic": "~11.2.7",
    "@angular/router": "~11.2.7",
    "@tailwindcss/forms": "^0.3.2",
    "@tailwindcss/typography": "^0.4.0",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.3"
  },
  "devDependencies": {
    "@angular-builders/jest": "^11.1.1",
    "@angular-devkit/build-angular": "~0.1102.7",
    "@angular/cli": "~11.2.6",
    "@angular/compiler-cli": "~11.2.7",
    "@compodoc/compodoc": "^1.1.11",
    "@storybook/addon-a11y": "^6.2.1",
    "@storybook/addon-actions": "^6.2.1",
    "@storybook/addon-docs": "^6.2.1",
    "@storybook/addon-knobs": "^6.2.1",
    "@storybook/addon-links": "^6.2.1",
    "@storybook/addon-storysource": "^6.2.1",
    "@storybook/addon-viewport": "^6.2.1",
    "@storybook/addons": "^6.2.1",
    "@storybook/angular": "^6.2.1",
    "@tailwindcss/postcss7-compat": "^2.1.0",
    "@types/jest": "^26.0.22",
    "@types/node": "^12.11.1",
    "autoprefixer": "^9.8.6",
    "codelyzer": "^6.0.0",
    "jest": "^26.6.3",
    "ng-packagr": "^11.0.0",
    "postcss": "^7.0.35",
    "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.1.0",
    "ts-jest": "^26.5.4",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.1.5"
  }
}

projects/test/storybook/src/stories/button.stories

import { boolean, text, select } from '@storybook/addon-knobs';
import { moduleMetadata } from '@storybook/angular';
import { CommonModule } from '@angular/common';
import {ButtonComponent, ButtonModule} from 'test';

const title = 'Button';
export default {
  title,
  component: ButtonComponent,
  decorators: [
    moduleMetadata({
      imports: [ButtonModule, CommonModule]
    })
  ]
};

const template = `
    <test-button
    [size]="size"
    [outline]="outline"
    [block]="block"
    [loading]="loading"
    [disabled]="disabled"
    (click)="clicked">
    {{content}}
    </test-button>
`;

const defaultProps = () => {
  return {
    content: text('content', 'text'),
    loading: boolean('loading', false),
    type: select('type', {
      text: 'text',
      submit: 'submit'
    }, 'text'),
    size: select('size', {
      sm: 'sm',
      lg: 'lg',
      xl: 'xl'
    }, null),
    outline: boolean('outline', null),
    block: boolean('block', null),
    disabled: boolean('disabled', null)
  };
};

export const Button = () => ({
  template,
  props: defaultProps()
});


projects/test/.../button.component.html


   <button class="px-4 border border-transparent shadow-sm text-sm font-medium rounded-md bg-red-400 text-primary py-2" [type]="type" [ngClass]="classes" [attr.disabled]="loading || disabled ? 'disabled' : null"
            (click)="clicked.emit($event)">
      <ng-content></ng-content>
    </button>`

tailwind.config.js

module.exports = {
  prefix: '',
  purge: {
  },
  darkMode: 'class', // or 'media' or 'class'
  theme: {
    extend: {
      colors: {
        primary: '#ecc94b',
      },
    },
  },
  variants: {
    extend: {},
  },
  plugins: [require('@tailwindcss/forms'),require('@tailwindcss/typography')],
};

Tailwind styles are not applied

button with no custom style

dev console

I don't know what is missing in my configuration

2 Answers

You can use this template which comes with Angular 12, Tailwind 2.1 JIT and Storybook 6.3. This repo also got atomic folder structure just in case you are into it. It's got the latest Ivy rendering pipeline as well, improves performance.

https://github.com/newwwton/angular-tailwind-storybook

I think your issue might be with the fact that storybook needs to have css files and not scss, so you need an appropriate webpack loader for your scss files.

I have this on my preview.js file and tailwind worked out of the box for me.

import '!style-loader!css-loader!./styles.css';

And my styles.scss contains the tailwind imports like you have:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

NB: you need to npm install style-loader and css-loader in your project

Related