tailwind 3.0.23 classes not being applied in real time in storybook
Asked Answered
B

2

6

not able to apply tailwind classes via storybook UI in real time, for example, changing the color of a button through the props classes here from bg-red-600 to bg-red-100 doesn't change the color of the button in the storybook ui, is it possible to change the color of the button from the UI to see what it would look like? (component works as expected in app, just not in the storybook)

not sure if this is related to purging or JIT compilation https://github.com/tailwindlabs/tailwindcss/discussions/6347

storybook ui

enter image description here

button component

<button
      type="button"
      className={clsx(
        "rounded-full py-2 px-3",
        classes,
        disabled ? "disabled:opacity-25" : ""
      )}
      onClick={onClick}
    >

tailwind.config.js

module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

button.stories.tsx

ButtonComponent.args = {
  label: "Button",
  classes: "bg-red-600",
  disabled: false,
};

preview.js

import "!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css";
import "../styles/globals.css";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

main.js

module.exports = {
  stories: [
    "../components/**/*.stories.mdx",
    "../components/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    {
      name: "@storybook/addon-postcss",
      options: {
        cssLoaderOptions: {
          // When you have splitted your css over multiple files
          // and use @import('./other-styles.css')
          importLoaders: 1,
        },
        postcssLoaderOptions: {
          // When using postCSS 8
          implementation: require("postcss"),
        },
      },
    },
  ],
  framework: "@storybook/react",
  staticDirs: ["../public"],
};

package.json dev dependencies

  "devDependencies": {
    "@babel/core": "^7.17.7",
    "@babel/eslint-parser": "^7.17.0",
    "@fullhuman/postcss-purgecss": "^4.1.3",
    "@storybook/addon-actions": "^6.5.0-alpha.51",
    "@storybook/addon-essentials": "^6.5.0-alpha.51",
    "@storybook/addon-interactions": "^6.5.0-alpha.51",
    "@storybook/addon-links": "^6.5.0-alpha.51",
    "@storybook/addon-postcss": "^2.0.0",
    "@storybook/react": "^6.5.0-alpha.51",
    "@storybook/testing-library": "^0.0.9",
    "@testing-library/dom": "^7.30.0",
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^10.4.7",
    "@testing-library/user-event": "^12.8.3",
    "@types/node": "^17.0.21",
    "@types/react": "^17.0.40",
    "autoprefixer": "^10.4.4",
    "babel-loader": "^8.2.3",
    "clsx": "^1.1.1",
    "enzyme": "^3.11.0",
    "eslint": "8.4.1",
    "eslint-config-next": "^12.1.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-storybook": "^0.5.7",
    "faker": "^5.4.0",
    "history": "^5.0.0",
    "html-webpack-plugin": "^5.5.0",
    "imports-loader": "^2.0.0",
    "jest": "^26.6.3",
    "jest-axe": "^6.0.0",
    "lodash": "^4.17.21",
    "postcss": "^8.4.12",
    "postcss-import": "^14.1.0",
    "storybook-addon-next": "^1.6.2",
    "tailwindcss": "^3.0.23",
    "typescript": "^4.2.4"
  },
Barty answered 28/3, 2022 at 2:52 Comment(6)
Do you have a tailwind.config.js file?Colpotomy
@RicardoCosta yup, just added it to the postBarty
Is your storybook components located under one of the paths inside content param in tailwind config file? It's also possible (but I am not really sure about this one) the wildcard can't reach the stories component and you might have to adapt the rule to be able to reach .stories.tsxColpotomy
yea the components are inside the components folder, i'm not sure how the storybook and tailwind work in real time to apply the class changeBarty
You should be able to inspect element and see if the color class is actually doing anything (if it gives a value to the css class) if not then most likely it is being purged by tailwind and you need to add the stories path in the tailwind content array (look at my edit on previous comment)Colpotomy
the class is added but no value is given to the css, so it does seem like it's being purged, i added ` "./components/**/*.stories.{js,ts,jsx,tsx}"` to the content array but that didn't help, the stories file is in the same folder as the component fileBarty
T
13

There is a config in tailwind called safelisting. This option said that tailwind classes don't apply when they change in real time and DOM.

read: https://tailwindcss.com/docs/content-configuration#safelisting-classes

you need to add specific classes to safelist to apply for changing in DOM and real-time. you can add all of tailwind classes to safe list by adding this config to your tailwind.config.js:

module.exports = {
  safelist: [
    {
      pattern: /^(.*?)/,
    },
  ],
  // ...
}
Tresa answered 29/3, 2022 at 5:1 Comment(4)
thank you SO SO much! searched 2h for thisBlount
Thank you! I couldn't imagine why it doesn't work.. never would come up with this by myselfSmalley
This was extremely helpful. Has anyone found a good way to only safelist for Storybook so we don't have to safelist our entire app? As they say in the Tailwinds docs, safe listing is a last resort. Thanks again though for revealing this fix!Vespertine
This is a bad solution. I did this and it took 15 seconds for my project to build because of 350K lines of CSS that have to be generated. Safelisting is a last-resort, and should only be used in situations where it’s impossible to scan certain content for class names.Freeload
F
0

Problem

To fix this problem correctly, it is very important that you understand the high-level overview of how Tailwind works.

Tailwind CSS works by scanning all of your HTML, JavaScript components, and any other template files for class names, then generating all of the corresponding CSS for those styles.

In order for Tailwind to generate all of the CSS you need, it needs to know about every single file in your project that contains any Tailwind class names.

In Layman's terms, Tailwind is simply a collection of pre-defined CSS code like the following:

.ring-offset-teal-500 {
  --tw-ring-offset-color: #14b8a6;
}
.ring-offset-teal-500\/0 {
  --tw-ring-offset-color: rgb(20 184 166 / 0);
}
.ring-offset-teal-500\/10 {
  --tw-ring-offset-color: rgb(20 184 166 / 0.1);
}

In the above CSS code, we have 3 class rules. It's simply a bunch of mapping between class names to CSS styles. Tailwind has thousands of class rules like this.

This means that Tailwind can be thought of as a single CSS file that you put in your project. The CSS file is about 500K lines of code. It's huge.

However, Tailwind knows that you are not going to use all the classes that Tailwind provides, so they scan your project to see which classes you actually use, allowing them to generate a much smaller CSS file for you.

The scanning process is a simple RegEx word-matching. It's not a smart algorithm but it's good enough. For example, they will search for any mention of ring-offset-teal-500 in your code. It can even be in the comment. If they find a match, they will generate CSS code corresponding to ring-offset-teal-500 class.

If they don't see your code files, they will generate a wrong CSS file that doesn't contain all the CSS code you need, causing some classes to not work.

In your case, the storybook components are probably stored in a location that is not seen by Tailwind scanning process. That's the problem.

Solution

If you want Tailwind to know about utility classes that you use in your storybook components, you need to add the directory to content section of tailwind.config.ts

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{html,js}',
    './components/**/*.{html,js}',
    './stories/**/*.{tsx,ts} // this is the location to your storybook components
  ],
  // ...
}

This will make sure that tailwind scans your storybook components for utility classes so that they can generate all necessary CSS code.

Do not use safelisting approach as that will just make the generated CSS file bigger than it needs to be, which lead to slow build process.

Freeload answered 27/4, 2024 at 14:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.