Skip to content

Commit 621d2fe

Browse files
committed
feat(Badge): add square prop
1 parent 4b3d2a7 commit 621d2fe

File tree

8 files changed

+109
-42
lines changed

8 files changed

+109
-42
lines changed

docs/content/3.components/badge.md

+15
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ slots:
6969
---
7070
::
7171

72+
### Square
73+
74+
Use the `square` prop to make the Badge squared.
75+
76+
::component-code
77+
---
78+
props:
79+
icon: i-lucide-rocket
80+
square: true
81+
size: md
82+
color: primary
83+
variant: solid
84+
---
85+
::
86+
7287
### Icon
7388

7489
Use the `icon` prop to show an [Icon](/components/icon) inside the Badge.

playground/app/pages/components/badge.vue

+17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ const variants = Object.keys(theme.variants.variant) as Array<keyof typeof theme
4242
<div class="flex items-center gap-2 ms-[-86px]">
4343
<UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" label="Badge" :size="size" />
4444
</div>
45+
<div class="flex items-center gap-2">
46+
<UBadge
47+
v-for="size in sizes"
48+
:key="size"
49+
icon="i-lucide-rocket"
50+
:size="size"
51+
/>
52+
</div>
53+
<div class="flex items-center gap-2 ms-[-86px]">
54+
<UBadge
55+
v-for="size in sizes"
56+
:key="size"
57+
icon="i-lucide-rocket"
58+
label="Badge"
59+
:size="size"
60+
/>
61+
</div>
4562
<div class="flex items-center gap-2 ms-[-86px]">
4663
<UBadge v-for="size in sizes" :key="size" :avatar="{ src: 'https://github.com/benjamincanac.png' }" label="Badge" :size="size" />
4764
</div>

src/runtime/components/Badge.vue

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export interface BadgeProps extends Omit<UseComponentIconsProps, 'loading' | 'lo
2626
* @defaultValue 'md'
2727
*/
2828
size?: Badge['variants']['size']
29+
/** Render the badge with equal padding on all sides. */
30+
square?: boolean
2931
class?: any
3032
ui?: Badge['slots']
3133
}
@@ -50,7 +52,7 @@ import UAvatar from './Avatar.vue'
5052
const props = withDefaults(defineProps<BadgeProps>(), {
5153
as: 'span'
5254
})
53-
defineSlots<BadgeSlots>()
55+
const slots = defineSlots<BadgeSlots>()
5456
5557
const appConfig = useAppConfig() as Badge['AppConfig']
5658
const { orientation, size: buttonGroupSize } = useButtonGroup<BadgeProps>(props)
@@ -60,6 +62,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.badge || {})
6062
color: props.color,
6163
variant: props.variant,
6264
size: buttonGroupSize.value || props.size,
65+
square: props.square || (!slots.default && !props.label),
6366
buttonGroup: orientation.value
6467
}))
6568
</script>

src/theme/badge.ts

+23
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ export default (options: Required<ModuleOptions>) => ({
5353
leadingAvatarSize: '2xs',
5454
trailingIcon: 'size-6'
5555
}
56+
},
57+
square: {
58+
true: ''
5659
}
5760
},
5861
compoundVariants: [...(options.theme.colors || []).map((color: string) => ({
@@ -87,6 +90,26 @@ export default (options: Required<ModuleOptions>) => ({
8790
color: 'neutral',
8891
variant: 'subtle',
8992
class: 'ring ring-inset ring-accented text-default bg-elevated'
93+
}, {
94+
size: 'xs',
95+
square: true,
96+
class: 'p-1'
97+
}, {
98+
size: 'sm',
99+
square: true,
100+
class: 'p-1.5'
101+
}, {
102+
size: 'md',
103+
square: true,
104+
class: 'p-2'
105+
}, {
106+
size: 'lg',
107+
square: true,
108+
class: 'p-2'
109+
}, {
110+
size: 'xl',
111+
square: true,
112+
class: 'p-2.5'
90113
}],
91114
defaultVariants: {
92115
color: 'primary',

test/components/Badge.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ describe('Badge', () => {
2121
['with avatar', { props: { avatar: { src: 'https://github.com/benjamincanac.png' } } }],
2222
['with avatar and leadingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, leadingIcon: 'i-lucide-arrow-left' } }],
2323
['with avatar and trailingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, trailingIcon: 'i-lucide-arrow-right' } }],
24+
['with square', { props: { icon: 'i-lucide-rocket', square: true } }],
2425
['with as', { props: { label: 'Badge', as: 'div' } }],
2526
['with class', { props: { label: 'Badge', class: 'rounded-full font-bold' } }],
2627
['with ui', { props: { label: 'Badge', ui: { label: 'font-bold' } } }],
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,92 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`Badge > renders with as correctly 1`] = `
4-
"<div class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted">
4+
"<div class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted">
55
<!--v-if--><span class="truncate">Badge</span>
66
<!--v-if-->
77
</div>"
88
`;
99

10-
exports[`Badge > renders with avatar and leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
10+
exports[`Badge > renders with avatar and leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
1111

1212
exports[`Badge > renders with avatar and trailingIcon correctly 1`] = `
13-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
13+
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-5 text-[10px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="20" height="20" class="h-full w-full rounded-[inherit] object-cover"></span>
1414
<!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"
1515
`;
1616
1717
exports[`Badge > renders with avatar correctly 1`] = `
18-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
18+
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-5 text-[10px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="20" height="20" class="h-full w-full rounded-[inherit] object-cover"></span>
1919
<!--v-if-->
2020
<!--v-if--></span>"
2121
`;
2222
2323
exports[`Badge > renders with class correctly 1`] = `
24-
"<span class="inline-flex items-center text-xs px-2 py-1 gap-1 bg-primary text-inverted rounded-full font-bold"><!--v-if--><span class="truncate">Badge</span>
24+
"<span class="inline-flex items-center text-xs px-2 py-1.5 gap-1 bg-primary text-inverted rounded-full font-bold"><!--v-if--><span class="truncate">Badge</span>
2525
<!--v-if--></span>"
2626
`;
2727
28-
exports[`Badge > renders with default slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if-->Default slot<!--v-if--></span>"`;
28+
exports[`Badge > renders with default slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted"><!--v-if-->Default slot<!--v-if--></span>"`;
2929
30-
exports[`Badge > renders with icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
30+
exports[`Badge > renders with icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
3131
3232
exports[`Badge > renders with label correctly 1`] = `
33-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
33+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
3434
<!--v-if--></span>"
3535
`;
3636
37-
exports[`Badge > renders with leading and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
37+
exports[`Badge > renders with leading and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
3838
39-
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted">Leading slot<!--v-if--><!--v-if--></span>"`;
39+
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5">Leading slot<!--v-if--><!--v-if--></span>"`;
4040
41-
exports[`Badge > renders with leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
41+
exports[`Badge > renders with leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
4242
4343
exports[`Badge > renders with neutral variant outline correctly 1`] = `
44-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md ring ring-inset ring-accented text-default bg-default"><!--v-if--><span class="truncate">Badge</span>
44+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md ring ring-inset ring-accented text-default bg-default"><!--v-if--><span class="truncate">Badge</span>
4545
<!--v-if--></span>"
4646
`;
4747
4848
exports[`Badge > renders with neutral variant soft correctly 1`] = `
49-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md text-default bg-elevated"><!--v-if--><span class="truncate">Badge</span>
49+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md text-default bg-elevated"><!--v-if--><span class="truncate">Badge</span>
5050
<!--v-if--></span>"
5151
`;
5252
5353
exports[`Badge > renders with neutral variant solid correctly 1`] = `
54-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md text-inverted bg-inverted"><!--v-if--><span class="truncate">Badge</span>
54+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md text-inverted bg-inverted"><!--v-if--><span class="truncate">Badge</span>
5555
<!--v-if--></span>"
5656
`;
5757
5858
exports[`Badge > renders with neutral variant subtle correctly 1`] = `
59-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md ring ring-inset ring-accented text-default bg-elevated"><!--v-if--><span class="truncate">Badge</span>
59+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md ring ring-inset ring-accented text-default bg-elevated"><!--v-if--><span class="truncate">Badge</span>
6060
<!--v-if--></span>"
6161
`;
6262
6363
exports[`Badge > renders with primary variant outline correctly 1`] = `
64-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md text-primary ring ring-inset ring-primary/50"><!--v-if--><span class="truncate">Badge</span>
64+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md text-primary ring ring-inset ring-primary/50"><!--v-if--><span class="truncate">Badge</span>
6565
<!--v-if--></span>"
6666
`;
6767
6868
exports[`Badge > renders with primary variant soft correctly 1`] = `
69-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary/10 text-primary"><!--v-if--><span class="truncate">Badge</span>
69+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary/10 text-primary"><!--v-if--><span class="truncate">Badge</span>
7070
<!--v-if--></span>"
7171
`;
7272
7373
exports[`Badge > renders with primary variant solid correctly 1`] = `
74-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
74+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
7575
<!--v-if--></span>"
7676
`;
7777
7878
exports[`Badge > renders with primary variant subtle correctly 1`] = `
79-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary/10 text-primary ring ring-inset ring-primary/25"><!--v-if--><span class="truncate">Badge</span>
79+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary/10 text-primary ring ring-inset ring-primary/25"><!--v-if--><span class="truncate">Badge</span>
8080
<!--v-if--></span>"
8181
`;
8282
8383
exports[`Badge > renders with size lg correctly 1`] = `
84-
"<span class="font-medium inline-flex items-center text-sm px-2 py-1 gap-1.5 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
84+
"<span class="font-medium inline-flex items-center text-sm px-2.5 py-2 gap-1.5 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
8585
<!--v-if--></span>"
8686
`;
8787
8888
exports[`Badge > renders with size md correctly 1`] = `
89-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
89+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
9090
<!--v-if--></span>"
9191
`;
9292
@@ -96,7 +96,7 @@ exports[`Badge > renders with size sm correctly 1`] = `
9696
`;
9797
9898
exports[`Badge > renders with size xl correctly 1`] = `
99-
"<span class="font-medium inline-flex items-center text-base px-2.5 py-1 gap-1.5 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
99+
"<span class="font-medium inline-flex items-center text-base px-3 py-2.5 gap-1.5 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
100100
<!--v-if--></span>"
101101
`;
102102
@@ -105,13 +105,15 @@ exports[`Badge > renders with size xs correctly 1`] = `
105105
<!--v-if--></span>"
106106
`;
107107
108-
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
108+
exports[`Badge > renders with square correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
109109
110-
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if-->Trailing slot</span>"`;
110+
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
111111
112-
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
112+
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><!--v-if--><!--v-if-->Trailing slot</span>"`;
113+
114+
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1.5"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
113115
114116
exports[`Badge > renders with ui correctly 1`] = `
115-
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate font-bold">Badge</span>
117+
"<span class="font-medium inline-flex items-center text-xs px-2 py-1.5 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate font-bold">Badge</span>
116118
<!--v-if--></span>"
117119
`;

0 commit comments

Comments
 (0)