From a206ceaa938bc3e05e8b99e77b6044bccd12ab67 Mon Sep 17 00:00:00 2001
From: Mathu-lmn <80094438+Mathu-lmn@users.noreply.github.com>
Date: Sun, 19 Apr 2026 15:53:07 +0200
Subject: [PATCH] feat(AvatarGroup): add overflow slot for custom tooltip on
hidden avatars
---
.../AvatarGroupOverflowTooltipExample.vue | 31 +++++++++++++++++++
.../content/docs/2.components/avatar-group.md | 6 ++++
src/runtime/components/AvatarGroup.vue | 10 +++++-
test/components/AvatarGroup.spec.ts | 23 ++++++++++++++
4 files changed, 69 insertions(+), 1 deletion(-)
create mode 100644 docs/app/components/content/examples/avatar-group/AvatarGroupOverflowTooltipExample.vue
diff --git a/docs/app/components/content/examples/avatar-group/AvatarGroupOverflowTooltipExample.vue b/docs/app/components/content/examples/avatar-group/AvatarGroupOverflowTooltipExample.vue
new file mode 100644
index 0000000000..53539b4c2a
--- /dev/null
+++ b/docs/app/components/content/examples/avatar-group/AvatarGroupOverflowTooltipExample.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/content/docs/2.components/avatar-group.md b/docs/content/docs/2.components/avatar-group.md
index 98e6e24c77..bc913242e4 100644
--- a/docs/content/docs/2.components/avatar-group.md
+++ b/docs/content/docs/2.components/avatar-group.md
@@ -69,6 +69,12 @@ slots:
:u-avatar{src="https://github.com/noook.png" alt="Neil Richter" loading="lazy"}
::
+### Overflow tooltip
+
+Use the `overflow` slot to customize the `+X` avatar. The slot receives the hidden count and the default avatar props, so you can wrap the overflow avatar with a [Tooltip](/docs/components/tooltip) and provide either a static string or a helper function that derives the label from the count.
+
+:component-example{name="avatar-group-overflow-tooltip-example"}
+
## Examples
### With tooltip
diff --git a/src/runtime/components/AvatarGroup.vue b/src/runtime/components/AvatarGroup.vue
index b11e0845b9..df67a008de 100644
--- a/src/runtime/components/AvatarGroup.vue
+++ b/src/runtime/components/AvatarGroup.vue
@@ -26,6 +26,7 @@ export interface AvatarGroupProps {
export interface AvatarGroupSlots {
default?(props?: {}): VNode[]
+ overflow?(props: { hiddenCount: number, avatarProps: { text: string, class: any } }): VNode[]
}
@@ -90,6 +91,11 @@ const hiddenCount = computed(() => {
return children.value.length - visibleAvatars.value.length
})
+const overflowAvatarProps = computed(() => ({
+ text: `+${hiddenCount.value}`,
+ class: ui.value.base({ class: uiProp.value?.base })
+}))
+
provide(avatarGroupInjectionKey, computed(() => ({
size: props.size
})))
@@ -97,7 +103,9 @@ provide(avatarGroupInjectionKey, computed(() => ({
-
+
+
+
diff --git a/test/components/AvatarGroup.spec.ts b/test/components/AvatarGroup.spec.ts
index 338875dd29..2310f2430a 100644
--- a/test/components/AvatarGroup.spec.ts
+++ b/test/components/AvatarGroup.spec.ts
@@ -19,6 +19,23 @@ const AvatarGroupWrapper = defineComponent({
`
})
+const AvatarGroupOverflowTooltipWrapper = defineComponent({
+ components: {
+ UAvatar: Avatar,
+ UAvatarGroup: AvatarGroup
+ },
+ template: `
+
+
+
+
+
+
+
+
+`
+})
+
describe('AvatarGroup', () => {
const sizes = Object.keys(theme.variants.size) as any
@@ -33,6 +50,12 @@ describe('AvatarGroup', () => {
['with default slot', {}]
])
+ it('exposes the hidden count to the overflow slot', async () => {
+ const wrapper = await mountSuspended(AvatarGroupOverflowTooltipWrapper)
+
+ expect(wrapper.find('[data-hidden-count="1"]').exists()).toBe(true)
+ })
+
it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(AvatarGroupWrapper, {
props: {