RyanClementsHax / tailwindcss-themer

An unopinionated, scalable, tailwindcss theming solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Storybook support

PhilippMolitor opened this issue · comments

Describe the bug

I am using storybook with tailwindcss. When running my app in dev mode, color theme switching works fine.
When using storybook, nothing happens to my styles, even though the class is correctly applied to the html node of the dom.

This is implemented with @storybook/addon-styling and this code in my .storybook/preview.ts:

export const decorators = [
  withThemeByClassName({
    themes: {
      dark: '',
      light: 'theme-light',
    },
    defaultTheme: 'dark',
  }),
]

Your minimal, reproducible example

none yet

Steps to reproduce

Install storybook and tailwindcss into a react+vite project, use tailwindcss-themer with @storybook/addon-styling

Expected behavior

As described.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

macOS, Chrome latest

tailwindcss-themer version

3.1.0

Additional context

No response

Thanks for opening the issue. I'd be happy to help. 😀

To do that I'll need a reproduction repo. I see you have instructions but the repo makes sure I see what you see while making things more maintainable on my end.

Hi, thanks for your swift reply. I was already working on an isolated example, as I am not able to share code from my actual project.
Here you go: https://codesandbox.io/p/sandbox/boring-leaf-x4yxsx

Thank you for taking the time.

Hello guys !
Any news about this issue ? I have the same problem as @PhilippMolitor, with the same code structure (just using Vue instead of React).
Variants system seams to work (with the addition of defaultTheme class in the DOM), even with Storybook switch :
defaultTheme:text-primary-xxx secondTheme:text-secondary-xxx
So I think the class generation works... ?

I haven't prioritized looking at it yet (resolving some issues on different projects) but I hope to get to it soon unless someone else is able to take ownership of this.

You could probably achieve the same result by simply providing a decorator as follows. Docs

const withThemeProvider = (Story, context) => {
  const theme = context.globals?.theme || 'default-theme';
  return (
    <div data-theme={theme}>
      <Story />
    </div>
  );
};
const preview: Preview = {
  globalTypes: {
    theme: {
      description: 'Global theme for components',
      defaultValue: 'default-theme',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'paintbrush',
        // Array of plain string values or MenuItem shape (see below)
        items: ['default-theme', 'theme-1', 'theme-2'],
        // Change title based on selected value
        dynamicTitle: true,
      },
    },
  },
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
  decorators: [withThemeProvider],
};

Sorry for the wait (things have been crazy on my end the last few months).

The issue you're experiencing actually has to do with tailwind's class detection. For those that want an in depth explanation, continue reading below, but you can fix this issue by including "theme-alt" anywhere in a file matched by your tailwind config's content field.

You can fix it by including .storybook/preview.ts in your tailwind config's content field.

You can even add something like this in your story file and be on your way.

const _ = "theme-alt"

Let me know if this fixes your issue @PhilippMolitor @SamyOuadhiGE


Now for the nerdy breakdown.

Tailwind generates a massive amount of classes due to all of the permutations derived from config. In order to make bundle sizes practical, tailwind inspects your code to see which classes you actually use and only includes those. The files it inspects is configured by your tailwind config's content field. On top of this, it expects to see the class represented in a string somewhere in those files. Thereby including something like const _ = "theme-alt" anywhere gets the related classes inserted in the bundle.

Also, even though .storybook/preview.ts has this string, it wasn't included by any of the globs in the content field.