flowbite-react icon indicating copy to clipboard operation
flowbite-react copied to clipboard

Tailwind prefix not considered

Open clari182 opened this issue 3 years ago • 19 comments
trafficstars

Is your feature request related to a problem? Please describe. I'm using tailwind configured with a prefix tw- but when using a flowbite-react component (for example Card) the prefix is not added to the card classes. So the tailwind styles are not applied.

Describe the solution you'd like It'd be great if the tailwind prefix defined in tailwind.config.js is applied to the component classes.

clari182 avatar Aug 22 '22 19:08 clari182

Yeah... TBH, I have NO idea how it can be done. :thinking: But, you can easy fix it right now, just prefixing the the css tags by creating a custom theme.

rluders avatar Aug 22 '22 20:08 rluders

How to use theme component: https://flowbite-react.com/theme

Default theme file: https://github.com/themesberg/flowbite-react/blob/main/src/lib/theme/default.ts

rluders avatar Aug 22 '22 20:08 rluders

Hey! Thanks, that's actually the workaround I'm using right now.

clari182 avatar Aug 23 '22 13:08 clari182

I have an idea here. Since we are using the theme system, we could try to get the prefix from tailwind.config.js and kind of "prefix" all the styles defined in the theme. Not sure how it will impact the performance, and how we can "build a static theme" from this... but maybe worth giving it a try and creating a PoC.

rluders avatar Nov 26 '22 13:11 rluders

@rluders Yeah, I think we can look into leveraging https://tailwindcss.com/docs/configuration#referencing-in-java-script

tulup-conner avatar Mar 02 '23 06:03 tulup-conner

~We probably will not work on this one. The best approach is to change the theme.~

rluders avatar Jul 25 '23 19:07 rluders

Perhaps I'm missing something here, but if I'm understanding this correctly, the suggestion is to update the theme to leverage the prefixes by adding an overriding entry for each component?

I don't see how that workaround is a workable solution.

If I'm changing the theme to apply prefixes to every component's properties, what's the purpose of integrating with the flowbite-react library?

nathguen avatar Jul 31 '23 17:07 nathguen

@nathguen since the classnames are basically strings, I don't see how we can automatically prefix them with the prefix configured in the tailwindcss configuration. But, anyway, if you have a better solution or suggestion, I'm open to hearing it.

rluders avatar Jul 31 '23 18:07 rluders

Just spitballing here.

I don't know the build processes for tailwind or postcss very well, but if there's a dictionary of all available class names, the build process could prefix any class name that matches inside a className property right?

How does TailwindCSS prefixes work currently?

nathguen avatar Aug 02 '23 21:08 nathguen

Sadly I am not sure how they do it, but since it is not mentioned here, it might be worth knowing that DaisyUI does exactly this. They even support the concept of 2 prefix types, both optional: One for the prefix of Tailwind classes, and another for the library ones.

Recently I had to gradually mix Tailwind into a project already using Bootstrap. Both define padding utilities with different sizes but the same name. With Daisy UI even the button class btn overlapped with Bootstrap too without a prefix.

fgarcia avatar Aug 03 '23 05:08 fgarcia

I was checking how DasyUI applies the prefix, and it seems that it is done at the PostCSS processing, it can be seen here.

I'll reopen this one, so, if @nathguen, @fgarcia, or anyone else were interested to submit a PR to implement this I'll be happy to review and accept it.

To me, it is not a huge priority, TBH... but probably something nice to have...

rluders avatar Aug 03 '23 08:08 rluders

we're migrating to flowbite-react, and are running into collision issues because we unfortunately have to keep bootstrap around a while longer.

the workaround mentioned above referenced custom themes, are you saying i will have to basically manually copy entire component styles and add the tailwind prefix (tw- for example) for each tailwind class?

benwharg avatar Aug 03 '23 18:08 benwharg

We are in a severe need of prefixing support for Flowbite React components. It enables a step-by-step replacement of old styling solutions that the tailwind classes would clash with. Our apps still make use of Boostrap that tailwind clashes with, thus we cannot start using Flowbite React without prefixing.

lars-jpeg avatar Oct 18 '23 07:10 lars-jpeg

How to use theme component: https://flowbite-react.com/theme

Default theme file: https://github.com/themesberg/flowbite-react/blob/main/src/lib/theme/default.ts

This was my solution, but it looks like thew newer Flowbite versions no longer have a giant theme file but instead localize each theme per component, so I cannot upgrade Flowbite :-(

jeremyisatrecharm avatar Oct 19 '23 16:10 jeremyisatrecharm

Reflecting on this, I have no idea how we would be able to fix this problem. Can anyone here expand more on their use case for this capability? I don't have any experience using prefixes in Tailwind CSS. Maybe there's something I'm missing.

tulup-conner avatar Nov 26 '23 20:11 tulup-conner

Reflecting on this, I have no idea how we would be able to fix this problem. Can anyone here expand more on their use case for this capability? I don't have any experience using prefixes in Tailwind CSS. Maybe there's something I'm missing.

There are several css utilities with the same name shared between TailwindCSS and Bootstrap for example. We have a legacy codebase that makes use of Bootstrap. These two for example:

https://getbootstrap.com/docs/4.0/utilities/visibility/ https://tailwindcss.com/docs/visibility

Now if I drop in a Flowbite React component into my codebae that also uses Bootstrap, some Bootstrap styles will get applied to the Flowbite components, and it is difficult to track where this happens and it causes bugs that are very difficult to troubleshoot.

It was mentioned earlier that DaisyUI supports prefixing. Maybe this repository could make use of the same technique as DaisyUI?

https://daisyui.com/docs/config/#prefix

How I see it is that the components should be prefixed with the prefix from either the tailwind config or a prefix passed to the Flowbite React plugin. This should happen before tailwind generates stylesheets with its JIT compiler.

lars-jpeg avatar Nov 27 '23 11:11 lars-jpeg

Since we are using twMerge to encapsulate all the classNames that receive the theme object, maybe we could find some way to apply the filters using it? 🤔

rluders avatar Nov 27 '23 11:11 rluders

Since we are using twMerge to encapsulate all the classNames that receive the theme object, maybe we could find some way to apply the filters using it? 🤔

Im not sure if you can use twMerge here as it is a runtime library and you would need to run the prefixing code before tailwind generates its stylesheets when building.

Look here to find out how DaisyUI does it: https://github.com/saadeghi/daisyui/blob/master/src/index.js

lars-jpeg avatar Nov 29 '23 12:11 lars-jpeg

This is my work-around. This will generate all of the tailwind classes used in Flowbite which is inefficient for bundle size because it's likely you don't use all of the components... But at least it works.

Step (1) create a custom theme

import type { FlowbiteTheme } from "flowbite-react";
import { theme } from "flowbite-react";

// MUST match tailwind.config.js.
const PREFIX = "tw-";

// XXX: This code does _not_ support important (!). I don't think this is used.
function prependToThemeClasses(themeObject: any): any {
  // A recursive function that will walk through the object tree
  const recurseObject = (obj: any): any => {
    return Object.fromEntries(
      Object.entries(obj).map(([key, value]) => {
        if (typeof value === "object" && !Array.isArray(value)) {
          // Recursive call if the value is another object
          return [key, recurseObject(value)];
        } else if (typeof value === "string") {
          // Process the string if it's indeed a string
          return [key, processClassString(value)];
        } else {
          // Keep the original value if it's not an object or string
          return [key, value];
        }
      })
    );
  };

  // Function to process a string of classes
  const processClassString = (classString: string): string => {
    return classString
      .split(" ") // Split the classes by spaces
      .map((className) => {
        if (className.trim().length === 0) {
          return "";
        }
        const isNegative = className.startsWith("-");
        const parts = className.split(":");

        const lastPart = parts[parts.length - 1];

        // Add the prefix to the last part of the className, after all modifiers
        parts[parts.length - 1] = `${PREFIX}${isNegative ? lastPart.slice(1) : lastPart}`;

        // If the className is negative, add the negative sign back
        if (isNegative) {
          parts[parts.length - 1] = `-${parts[parts.length - 1]}`;
        }

        return parts.join(":");
      })
      .join(" "); // Join the processed classes back together
  };

  return recurseObject(themeObject);
}

// Usage
export const CustomTheme = prependToThemeClasses(theme);

Step (2) wrap React app in theme (in my _app.tsx in Next):

     <Flowbite theme={{ theme: CustomTheme }}>
   ...
  </Flowbite>

Step (3) (!!)

  • Save CustomTheme to a javascript file in a path listed in a Tailwind config content directory.
  • It's pretty easy to just call JSON.stringify(CustomTheme, null, 2) and write that to a file.

jeremyisatrecharm avatar Jan 15 '24 17:01 jeremyisatrecharm