Skip to content

Handle responsiveness to avoid flickering of the UI ​

NOTE

This should not be used excessively. As you'll see, we use safelist, which forces Tailwind to recognize all possible CSS class combinations for variants and compoundVariants, ensuring they are included in the final build.

Use case: We want to let the user define what size of the button they want based on the breakpoints.

To use responsive variants we will set up things like this:

Create tailwind-buddy-interface.ts ​

ts
export type Screens = "sm" | "md";
export const screens: Screens[] = ["sm", "md"]; // or use Tailwind default screens

In your tailwind.config.ts Make sure to update the config ​

ts
import { screens } from "./tailwind-buddy-interface";
import { buttonVariants } from "./src/components/Button/Button.variants";
import { labelVariants } from "./src/components/Label/Label.variants";
import { generateSafeList } from "@busbud/tailwind-buddy";

/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx,mdx}"],
  theme: {
    screens,  
  },
  safelist: generateSafeList([labelVariants, buttonVariants], screens),  
};

Update now your component definition ​

ts
import { compose, VariantProps } from "@busbud/tailwind-buddy";

type ComposeType = {
  "slots": ["root"],
  variants: {
    size: ["small", "big"]
  },
  props: {},
  screens: typeof screens 
}

export const simpleVariants = compose<ComposeType>({
    slots: {
        "root": /** @tw */ "p-4"
    },
    variants: {
        size: {
            "small": "w-[400px] h-[200px]",
            "big": "w-[1000px] h-[600px]",
        }
    },
    defaultVariants: {
        variant: "small"
    },
    responsiveVariants: ["size"]  
})

export type SimpleProps = VariantProps<ComposeType["variants"], ComposeType["screens"]>; // make sure to now pass the screens to the generic type

See usage ​

tsx

<div>
  <SimpleComponent size="small" />
  <SimpleComponent size={{
    initial: "sm", // initial should always be defined in this case
    lg: "big" // at the end will generate the string p-4 w-[400px] h-[200px] lg:w-[1000px] lg:h-[600px]
  }} />
</div>

Specificity for TAILWIND 4 ​

We do have a project example using Tailwind v4. Tailwind 4 does not currently support the Tailwind 3 safelist. In that case we need to generate the file so that Tailwind will know which CSS classes are used.

To achieve that you can use our technique:

  • Create generate-safelist.ts
ts
import { generateSafeList } from "@busbud/tailwind-buddy";
import { screens, buttonVariants } from "./src/components/Button/Button.variants.js";
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const safelist = generateSafeList([buttonVariants], screens);

const fileContent = `// Auto-generated file - DO NOT EDIT
// Generated on: ${new Date().toISOString()}

export default ${JSON.stringify(safelist, null, 2)};
`;

fs.writeFileSync(
  path.resolve(__dirname, 'generated-safelist.ts'),
  fileContent,
  'utf-8'
);

console.log('Safelist generated successfully!');
  • Update your package.json
json
scripts: {
  "safelist-generation": "node --import=tsx ./safelist-generation.ts",
  "prebuild": "pnpm safelist-generation",
  // ...
}

This should achieve the exact same as using the safelist