Skip to content

[ui5-avatar-group]: UI5 AvatarGroup keeps role="button" and tab stop even when there are no overflow avatars to expand #13677

@zhangliangyi

Description

@zhangliangyi

Bug Description

<ui5-avatar-group type="Group"> (default) unconditionally exposes:

  • role="button",
  • tabindex="0",
  • the accessible-name suffix "Activate for complete list.",
  • a click/Enter/Space activator.

The component's only built-in interactive action is "reveal the avatars hidden by overflow" — handled inside the component via _overflowItems() / _fireGroupEvent(). When _hiddenItems === 0 (every avatar fits the container), there is nothing to reveal.
Pressing Enter still fires ui5-click but the visible UI does not change, and a screen-reader user is told the element is an activatable button that does nothing. WCAG 2.2 SC 4.1.2 (Name, Role, Value) is violated in this state.

Root cause (in UI5 source)

packages/main/src/AvatarGroup.ts (verified against installed dist/AvatarGroup.js, lines 202-203 and 217-219):

  get _role() {
    return this._isGroup ? "button" : "group";          // hard-coded on `type`, ignores _hiddenItems
  }
  get _groupTabIndex() {
    return this._isGroup ? 0 : -1;                      // hard-coded on `type`, ignores _hiddenItems
  }

…and _ariaLabelText (lines 170-189):

  if (this._isGroup) {
    text += AvatarGroup_1.i18nBundle.getText(AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL);
    // → "Activate for complete list."
  }

_isGroup is decided purely from this.type === "Group". Whether the group has anything to expand (this._hiddenItems > 0) is recomputed every render in _setHiddenItems/_overflowItems, but it is not consulted in _role, _groupTabIndex, or _ariaLabelText.
Result: when _hiddenItems === 0 the activator semantics are still advertised even though _fireGroupEvent has nothing to surface.

Affected Component

ui5-avatar-group

Expected Behaviour

Proposed fix

Gate the button affordance on _hiddenItems:

  get _role() {
    if (!this._isGroup) return "group";
    return this._hiddenItems > 0 ? "button" : "group";
  }

  get _groupTabIndex() {
    if (!this._isGroup) return -1;
    return this._hiddenItems > 0 ? 0 : -1;
  }

  // in _ariaLabelText, only append AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL when this._hiddenItems > 0

Because _setHiddenItems already triggers a re-render (_hiddenItems is a reactive property), the role/tabindex/announcement will update correctly when the container is resized and avatars become hidden or revealed.

Isolated Example

No response

Steps to Reproduce

Steps to reproduce (no overflow case)

  <div style="width: 600px">
    <ui5-avatar-group type="Group">
      <ui5-avatar><img src="a.jpg" /></ui5-avatar>
      <ui5-avatar><img src="b.jpg" /></ui5-avatar>
      <ui5-avatar><img src="c.jpg" /></ui5-avatar>
    </ui5-avatar-group>
  </div>
  1. Tab into the group.
  2. Screen reader (NVDA / JAWS / VoiceOver) announces "button — Conjoined avatars. Displayed 3 of 3. Activate for complete list."
  3. Press Enter.
  4. Expected: Either there is something to activate, or the element does not announce as a button. Per ARIA / WCAG: a control should not claim a role/affordance it cannot fulfill.
  5. Actual: ui5-click fires, nothing observable changes, focus stays on the group. AT users perceive a broken button.

Log Output, Stack Trace or Screenshots

No response

Priority

None

UI5 Web Components Version

2.22.0

Browser

Edge

Operating System

No response

Additional Context

No response

Organization

SF

Declaration

  • I’m not disclosing any internal or sensitive information.

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    Status
    Issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions