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: {