Skip to content

Commit cfbc771

Browse files
jasonvargaclaude
andauthored
[6.x] Merge external class attrs through twMerge in UI components (#14379)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 48a1de0 commit cfbc771

3 files changed

Lines changed: 33 additions & 7 deletions

File tree

resources/js/components/ui/Badge.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<script setup>
2-
import { computed, useSlots } from 'vue';
2+
import { computed, useAttrs, useSlots } from 'vue';
33
import { cva } from 'cva';
44
import { twMerge } from 'tailwind-merge';
55
import Icon from './Icon/Icon.vue';
66
import { Link } from '@inertiajs/vue3';
77
8+
defineOptions({ inheritAttrs: false });
9+
810
const props = defineProps({
911
/** Appended text */
1012
append: { type: [String, Number, Boolean, null], default: null },
@@ -30,6 +32,7 @@ const props = defineProps({
3032
text: { type: [String, Number, Boolean, null], default: null },
3133
});
3234
35+
const attrs = useAttrs();
3336
const slots = useSlots();
3437
const hasDefaultSlot = !!slots.default;
3538
const tag = computed(() => {
@@ -78,12 +81,17 @@ const badgeClasses = computed(() => {
7881
asButton: props.href ?? props.as == 'button' ? true : false,
7982
});
8083
81-
return twMerge(classes);
84+
return twMerge(classes, attrs.class);
85+
});
86+
87+
const restAttrs = computed(() => {
88+
const { class: _, ...rest } = attrs;
89+
return rest;
8290
});
8391
</script>
8492
8593
<template>
86-
<component :is="tag" :class="badgeClasses" :href="props.href" :target="target" data-ui-badge>
94+
<component :is="tag" v-bind="restAttrs" :class="badgeClasses" :href="props.href" :target="target" data-ui-badge>
8795
<span v-if="props.prepend" class="font-medium border-e border-inherit ps-0.5 pe-1.5">{{ prepend }}</span>
8896
<Icon v-if="icon" :name="icon" />
8997
<slot v-if="hasDefaultSlot" />

resources/js/components/ui/Button/Button.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<script setup>
2-
import { computed, useSlots } from 'vue';
2+
import { computed, useAttrs, useSlots } from 'vue';
33
import { cva } from 'cva';
44
import { twMerge } from 'tailwind-merge';
55
import Icon from '../Icon/Icon.vue';
66
import { Link } from '@inertiajs/vue3';
77
8+
defineOptions({ inheritAttrs: false });
9+
810
const props = defineProps({
911
/** The element or component this component should render as */
1012
as: { type: String, default: null },
@@ -35,6 +37,7 @@ const props = defineProps({
3537
variant: { type: String, default: 'default' },
3638
});
3739
40+
const attrs = useAttrs();
3841
const slots = useSlots();
3942
const hasDefaultSlot = !!slots.default;
4043
const tag = computed(() => {
@@ -109,13 +112,19 @@ const buttonClasses = computed(() => {
109112
iconOnly: iconOnly.value,
110113
});
111114
112-
return twMerge(classes);
115+
return twMerge(classes, attrs.class);
116+
});
117+
118+
const restAttrs = computed(() => {
119+
const { class: _, ...rest } = attrs;
120+
return rest;
113121
});
114122
</script>
115123

116124
<template>
117125
<component
118126
:is="tag"
127+
v-bind="restAttrs"
119128
:class="buttonClasses"
120129
:disabled="disabled || loading"
121130
:data-ui-group-target="['subtle', 'ghost'].includes(props.variant) ? null : true"

resources/js/components/ui/Toggle/Item.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<script setup>
2-
import { computed, inject, useSlots } from 'vue';
2+
import { computed, inject, useAttrs, useSlots } from 'vue';
33
import { cva } from 'cva';
44
import { twMerge } from 'tailwind-merge';
55
import { ToggleGroupItem } from 'reka-ui';
66
import Icon from '../Icon/Icon.vue';
77
8+
defineOptions({ inheritAttrs: false });
9+
810
const props = defineProps({
911
/** Value of the toggle item */
1012
value: { type: String, required: true },
@@ -18,6 +20,7 @@ const props = defineProps({
1820
ariaDescribedby: { type: String, default: null },
1921
});
2022
23+
const attrs = useAttrs();
2124
const variant = inject('toggleVariant', 'default');
2225
const size = inject('toggleSize', 'base');
2326
@@ -78,12 +81,18 @@ const toggleItemClasses = computed(() => {
7881
iconOnly: iconOnly.value,
7982
});
8083
81-
return twMerge(classes);
84+
return twMerge(classes, attrs.class);
85+
});
86+
87+
const restAttrs = computed(() => {
88+
const { class: _, ...rest } = attrs;
89+
return rest;
8290
});
8391
</script>
8492

8593
<template>
8694
<ToggleGroupItem
95+
v-bind="restAttrs"
8796
:value="value"
8897
:aria-label="accessibleLabel"
8998
:aria-describedby="ariaDescribedby"

0 commit comments

Comments
 (0)