nextui-org / tailwind-variants

🦄 Tailwindcss first-class variant API
https://tailwind-variants.org
MIT License
2.42k stars 70 forks source link

extended tailwind classes not added to final classList. #69

Closed MarkLyck closed 1 year ago

MarkLyck commented 1 year ago

Describe the bug I have extended my tailwind theme with new a new class for a smaller fontSize:

fontSize: {
        mini: ['0.65rem', '0.75rem'],
      },

But when trying to use it in a tailwind-variants function. It never gets added to the final classes:

e.g.

export const itemDescription = tv({
  base: 'm-0 overflow-hidden whitespace-nowrap text-mini text-neutral-400',
})

The only workaround I have found is to override the class like tv({ class: 'text-mini '}) (this makes it work).

Expected behavior extended tailwind theme options should work in the tv() base classes.

Desktop (please complete the following information):

adnanalbeda commented 1 year ago

They are working for me.

What doesn't work is when I use the extended utility with attribute variant like this: focus:text-mini

mashouf commented 1 year ago

I have a similar issue. I customized the tailwind config and added different font sizes and colors, Tailwind variants do not understand the difference between text-[customized-color] and text-[customized-size], and the final class name does not include one of these. I mean the size overwrites the color or vice-versa. I have used text-[customized-size] in variants and text-[customized-color] in compoundedVariants.

mskelton commented 1 year ago

Tailwind merge doesn't load information from your Tailwind config automatically. You'll need to configure it for your custom class names following these guides:

der-daniel commented 1 year ago

@mskelton

Can you please elaborate a little bit more? Just using Tailwind, it sure does load my config automatically.

I expected tv to just work with my tailwind.config.js.

mskelton commented 1 year ago

Tailwind variants and tailwind-merge do not load the tailwind.config.js file since they operate at runtime and importing the tailwind config file would result in the tailwindcss package being bundled into the application as well, which would greatly increase bundle size. You can see in the tailwind-merge docs exactly what I'm saying.

The tailwind-merge config is different from the Tailwind config because it's expected to be shipped and run in the browser as opposed to the Tailwind config which is meant to run at build-time. Be careful in case you're using your Tailwind config directly to configure tailwind-merge in your client-side code because that could result in an unnecessarily large bundle size.

That's the reason why it's not loaded automatically. Tailwind runs at build time, tailwind-variants/tailwind-merge run at runtime.

GimpMaster commented 7 months ago

So I have the same problem. I have some special tailwind.config.js classes such as a button font size from my designer.

So in my tailwind.config.js I have text-button

twMerge and thus it seems tailwind variants drops these.

I'm curious if someone has a quick example of extending the tailwind merge config to just add a couple extra classes? If I find out how to I'll post back.

mskelton commented 7 months ago

@GimpMaster See my answer for documentation links: https://github.com/nextui-org/tailwind-variants/issues/69#issuecomment-1725410594

GimpMaster commented 7 months ago

@mskelton - I get that I'm just new to tv and tw-merge.

So I was looking for a simple working example. I'll post one when I can if I get it working.

I'm guessing it will be something like

const buttonVariants = tv({
    base: 'px-32 py-16 inline-flex items-center justify-center rounded-md font-semibold whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
    variants: {
        variant: {
            contained:
                'hover:border-neutral-grey-800 hover:bg-button-primary-hover active:bg-button-primary-active bg-primary-blue-500 text-neutral-white rounded-20',
            destructive:
                'bg-button-danger-enabled hover:bg-button-danger-hover active:bg-button-danger-active text-neutral-white rounded-20',
            outlined:
                'hover:border-button-primary-hover hover:text-button-primary-hover active:border-button-primary-active active:bg-button-primary-active-alt active:text-button-primary-active border-solid border-2 border-primary-blue-500 text-primary-blue-500 rounded-20',
            text: 'text-primary-blue-500 px-32 py-16  hover:text-button-primary-hover active:text-button-primary-active active:bg-button-primary-active-alt  rounded-20'
        }
    },
    defaultVariants: {
        variant: 'contained',
        size: 'default'
    }
}, {
    twMergeConfig: {
        BLAH: 'BLAH'
    }
});

where I need to figure out how to do BLAH BLAH for my custom font sizes

GimpMaster commented 7 months ago

Ok for anyone coming across this in the future here is a working example. It would be awesome to add something like this to the docs.

import { defaultConfig } from 'tailwind-variants';

defaultConfig.twMergeConfig = {
    classGroups: {
        customFontSizes: [
            'text-display1',
            'text-h1',
            'text-h1-desktop',
            'text-h2',
            'text-h2-desktop',
            'text-h2',
            'text-h3',
            'text-h3-desktop',
            'text-h4',
            'text-h4-desktop',
            'text-h5',
            'text-h5-desktop',
            'text-h6',
            'text-h6-desktop',
            'text-subheader1',
            'text-subheader2',
            'text-body1',
            'text-body2',
            'text-caption1',
            'text-caption2',
            'text-overline',
            'text-button'
        ]
    }
};

In this case I modified the default config for all tv() functions. You could just as easily pass it in on each tv() function but this was better to cover all cases.

Also if you are using shadcn-svelte I went a step further since they use clsx and twMerge in a wrapper function called cn()

import { defaultConfig } from 'tailwind-variants';

// Since we are using custom font sizes, we need to define the class groups for both tailwind-variants and tailwind-merge
const classGroups = {
    customFontSizes: [
        'text-display1',
        'text-h1',
        'text-h1-desktop',
        'text-h2',
        'text-h2-desktop',
        'text-h2',
        'text-h3',
        'text-h3-desktop',
        'text-h4',
        'text-h4-desktop',
        'text-h5',
        'text-h5-desktop',
        'text-h6',
        'text-h6-desktop',
        'text-subheader1',
        'text-subheader2',
        'text-body1',
        'text-body2',
        'text-caption1',
        'text-caption2',
        'text-overline',
        'text-button'
    ]
};

// This updates the tailwind-variants default config to include the customFontSizes class group
defaultConfig.twMergeConfig = {
    classGroups
};

// This is a custom tailwind-merge function that we can use with cn
const customTwMerge = extendTailwindMerge<'customFontSizes'>({
    //extend: { classGroups: { customFontSizes: ['text-button'] } }
    extend: { classGroups }
});

// This function combines clsx and customTwMerge to create a custom class name function.
// This allows us to use clsx style formatting such as cn('text-button', { 'text-primary-blue-500' : isPrimary}) and have it properly tailwind merge
export function cn(...inputs: ClassValue[]) {
    return customTwMerge(clsx(inputs));
}

Hopefully this helps someone else.