Bin
2025-12-17 611bfe34c3c96199eaaf6cf9e41a75892e44e879
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import type { StorybookConfig } from "@storybook/react-webpack5";
 
const config: StorybookConfig = {
  stories: ["../../../libs/**/*.@(mdx|stories.@(js|jsx|ts|tsx))", "../../../apps/**/*.@(mdx|stories.@(js|jsx|ts|tsx))"],
 
  staticDirs: ["../public"],
 
  addons: ["@nx/react/plugins/storybook", "@storybook/addon-docs", "../addons/theme-toggle/register"],
 
  webpackFinal(config) {
    const css_prefix = "ls-";
    const rules = config.module?.rules ?? [];
 
    for (const rule of rules) {
      if (!rule || typeof rule === "string") continue;
 
      const testString = rule.test?.toString() ?? "";
      const isCss = testString.includes("\\.css");
      const isScss = testString.includes("scss") || testString.includes("sass");
 
      if (isCss) {
        rule.exclude = /tailwind\.css/;
      }
 
      // Apply BEM class prefixing to non-module SCSS files
      if (isScss && rule.oneOf) {
        const scssRules = rule.oneOf.filter((r: any) => {
          if (!r.use) return false;
          const testString = r.test?.toString() ?? "";
          // Skip CSS modules and node_modules
          if (testString.match(/module/) || r.exclude?.toString().includes("node_modules")) return false;
          // Target rules with css-loader
          return (
            testString.match(/scss|sass/) &&
            Array.isArray(r.use) &&
            r.use.some((u: any) => u.loader && u.loader.includes("css-loader"))
          );
        });
 
        scssRules.forEach((r: any) => {
          const cssLoader = r.use.find((use: any) => use.loader && use.loader.includes("css-loader"));
 
          if (cssLoader && cssLoader.options) {
            cssLoader.options.modules = {
              localIdentName: `${css_prefix}[local]`,
              getLocalIdent(ctx: any, _ident: any, className: string) {
                // Skip prefixing for Storybook preview styles (targets Storybook DOM classes)
                if (ctx.resourcePath?.includes("preview.scss")) return className;
                if (className.includes("ant")) return className;
              },
            };
          }
        });
      }
    }
 
    return {
      ...config,
      module: {
        ...(config.module ?? {}),
        rules: [
          {
            test: /tailwind\.css/,
            exclude: /node_modules/,
            use: [
              "style-loader",
              {
                loader: "css-loader",
                options: {
                  importLoaders: 1,
                },
              },
              "postcss-loader",
            ],
          },
 
          ...(config.module?.rules ?? []),
        ],
      },
    };
  },
 
  framework: "@storybook/react-webpack5",
 
  typescript: {
    reactDocgen: "react-docgen",
  },
};
 
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