dcastil/tailwind-merge

`twMerge` strips `leading-x` classes

jeniabrook opened this issue · 6 comments

Describe the bug

If a leading-x class is at the beginning of the class list, twMerge removes it.

This is a bug that I discovered accidentally while using a custom Tailwind config. I added an eslint-plugin-tailwindcss to help sort classes, but after linting, some components that used leading-x classes were moved to the beginning of the class list, causing tests to fail.

I am using a utility function (from @shadcn) https://github.com/shadcn/ui/blob/main/apps/www/lib/utils.ts#L4 to wrap twMerge, and I have verified that the bug is indeed in twMerge.

As for my custom Tailwind config, I created a plugin that maps lineHeight to a different scale.

lineHeight: {
    '40': 'var(--line-height-40)',
	//...
}

According to the twMerge documentation, it should not be affecting the outcome.

To Reproduce

I've created a codesandbox: https://codesandbox.io/s/elated-fog-l7chww

Expected behavior

The expected behavior is that the leading-x classes should be preserved and not stripped out by the twMerge utility function.

Environment

  • tailwind-merge version: 1.12.0

It was also confirmed that the issue still occurs with the latest version of tailwind-merge.

Hey @jeniabrook! 👋

That is intended because text-2xl adds a line-height CSS property, overriding leading-1 if you place it afterwards. If you want to change this overriding behavior, here is a way on how to do it: #218 (comment)

It's unfortunate that eslint-plugin-tailwindcss sorts the classes this way. Maybe it would make sense to open an issue about this problem.

Related: #218, #187, #59

Thanks! After reading the related issues that you've mentioned, it makes sense.

I will open an issue in eslint-plugin-tailwindcss.

Just researched a bit and eslint-plugin-tailwindcss seems to use prettier-plugin-tailwindcss internally (source) which should order font-size classes before line-height classes.

If it orders them the other way around, it might be that prettier-plugin-tailwindcss can't find your tailwind.config.js and therefore treats leading-40 as a non-Tailwind class and puts it into the front. You can configure prettier and tell it explicitly where your tailwind config is: https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/v0.3.0/README.md#customizing-your-tailwind-config-path

@dcastil thanks!

I've set it correctly, and it seems working, but I have another problem now.

When linting via CLI, it indeed warns about the leading-x, after running the --fix flag, it puts them after the text-x classes, then in VSCode it warns me about the same eslint rule being violated, and after saving the file in VSCode it "fixes" back to the wrong order 🤷‍♂️.

It looks like the VSCode eslint and the CLI eslint are conflicting.

Hmmm looks like your VS Code ESLint/Prettier doesn't know about the config but the CLI does.

Yep, found the problem :)
I needed to add this to my settings.json, since I'm using a monorepo

"eslint.workingDirectories": [
    { "pattern": "./apps/*/" },
    { "pattern": "./packages/*/" }
  ]