Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 81 additions & 1 deletion packages/main/cypress/specs/Avatar.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,86 @@ describe("Accessibility", () => {
.should("have.attr", "aria-label", expectedLabel);
});

it("should return accessibilityInfo object when avatar is interactive", () => {
const INITIALS = "JD";
const hasPopup = "menu";
const customLabel = "John Doe Avatar";

cy.mount(
<Avatar
id="interactive-info"
initials={INITIALS}
interactive
accessibleName={customLabel}
accessibilityAttributes={{hasPopup}}
></Avatar>
);

cy.get("#interactive-info").then($avatar => {
const avatar = $avatar[0] as any;

// Check accessibilityInfo properties
expect(avatar.accessibilityInfo).to.exist;
expect(avatar.accessibilityInfo.role).to.equal("button");
expect(avatar.accessibilityInfo.type).to.equal(hasPopup);
expect(avatar.accessibilityInfo.description).to.equal(customLabel);
});
});

it("should return undefined for accessibilityInfo when avatar is not interactive", () => {
cy.mount(
<Avatar
id="non-interactive-info"
initials="JD"
></Avatar>
);

cy.get("#non-interactive-info").then($avatar => {
const avatar = $avatar[0] as any;

// Check that accessibilityInfo is undefined
expect(avatar.accessibilityInfo).to.be.undefined;
});
});

it("should return undefined for accessibilityInfo when avatar is interactive but disabled", () => {
cy.mount(
<Avatar
id="disabled-interactive-info"
initials="JD"
interactive
disabled
></Avatar>
);

cy.get("#disabled-interactive-info").then($avatar => {
const avatar = $avatar[0] as any;

// Check that accessibilityInfo is undefined because disabled overrides interactive
expect(avatar.accessibilityInfo).to.be.undefined;
});
});

it("should use default label for accessibilityInfo description when no custom label is provided", () => {
const INITIALS = "AB";

cy.mount(
<Avatar
id="default-label-info"
initials={INITIALS}
interactive
></Avatar>
);

cy.get("#default-label-info").then($avatar => {
const avatar = $avatar[0] as any;

// Check that accessibilityInfo uses the default label format that includes initials
expect(avatar.accessibilityInfo).to.exist;
expect(avatar.accessibilityInfo.description).to.equal(`Avatar ${INITIALS}`);
});
});

it("checks if accessible-name is correctly passed to the icon", () => {
const ACCESSIBLE_NAME = "Supplier Icon";
const ICON_NAME = "supplier";
Expand Down Expand Up @@ -500,4 +580,4 @@ describe("Avatar Rendering and Interaction", () => {
cy.get("@clickStub")
.should("have.been.calledOnce");
});
});
});
14 changes: 13 additions & 1 deletion packages/main/src/Avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
import type { AccessibilityAttributes, AriaRole } from "@ui5/webcomponents-base/dist/types.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import type { ITabbable } from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
Expand Down Expand Up @@ -493,6 +493,18 @@ class Avatar extends UI5Element implements ITabbable, IAvatarGroupItem {
}
this._imageLoadError = true;
}

get accessibilityInfo() {
if (this._interactive) {
return {
role: this._role as AriaRole,
type: this._ariaHasPopup,
description: this.accessibleNameText,
};
}

return undefined;
}
}

Avatar.define();
Expand Down
Loading