Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicated classes #363

Open
s-premswork opened this issue Dec 28, 2023 · 2 comments
Open

Duplicated classes #363

s-premswork opened this issue Dec 28, 2023 · 2 comments
Labels
context-v2 Related to tailwind-merge v2

Comments

@s-premswork
Copy link

Describe the bug

It seems that somehow my classes get added multiple times to my component.

To Reproduce

Have a component, e.g:
SecondaryButton.vue

<script setup>
import { twMerge } from 'tailwind-merge';
import { computed, useAttrs } from 'vue';

defineProps({
    type: {
        type: String,
        default: 'button',
    },
});

// Get element attributes
const attrs = useAttrs();
// Get classes defined on component
const extraClasses = attrs.class;
// Default input styling
const defaultClasses = 'inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 disabled:opacity-25';
// Merge classes with tailwind-merge to prevent conflicts
const computedClasses = computed(() => twMerge(defaultClasses, extraClasses));
</script>

<template>
  <button
    :type="type"
    :class="computedClasses"
  >
    <slot />
  </button>
</template>

Use the component:

<SecondaryButton class="p-2">
    Edit User
</SecondaryButton>

Expected behavior

I obviously expect that the component renders with the following class list:

inline-flex items-center justify-center rounded-md border border-gray-300 bg-white text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 disabled:opacity-25 p-2

But it outputs the following:

<button
    type="button"
    class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 disabled:opacity-25 p-2 p-2">
    Edit User
</button>

As you see, it adds the class `p-2` given in the `<SecondaryButton class="p-2">` twice. Not sure why it keeps doing this for me.

Environment

  • tailwind-merge version: 2.2.0
@dcastil dcastil added the context-v2 Related to tailwind-merge v2 label Dec 29, 2023
@dcastil
Copy link
Owner

dcastil commented Dec 29, 2023

Hey @s-premswork! 👋

This is a Vue feature that is a bit implicit and is not related to tailwind-merge. From the Vue docs:

When you use the class attribute on a component with a single root element, those classes will be added to the component's root element and merged with any existing class already on it.

For example, if we have a component named MyComponent with the following template:

<!-- child component template -->
<p class="foo bar">Hi!</p>

Then add some classes when using it:

<!-- when using the component -->
<MyComponent class="baz boo" />

The rendered HTML will be:

<p class="foo bar baz boo">Hi!</p>

Related: #76

@andredewaard
Copy link

andredewaard commented Jan 29, 2024

You can probably fix this by adding a 'class' prop to the component and handle the class yourself

<script setup>
import { twMerge } from 'tailwind-merge';
import { computed, useAttrs } from 'vue';

const props = defineProps({
    type: {
        type: String,
        default: 'button',
    },
    class: {
      type: String,
      required: false
    }
});

// Default input styling
const defaultClasses = 'inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 disabled:opacity-25';
// Merge classes with tailwind-merge to prevent conflicts
const computedClasses = computed(() => twMerge(defaultClasses, props.class));
</script>

<template>
  <button
    :type="type"
    :class="computedClasses"
  >
    <slot />
  </button>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
context-v2 Related to tailwind-merge v2
Projects
None yet
Development

No branches or pull requests

3 participants