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
67 changes: 66 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,71 @@ describe("Accessibility", () => {
.should("have.attr", "aria-label", expectedLabel);
});

it("should return correct 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("Button");
expect(avatar.accessibilityInfo.description).to.equal(customLabel);
});
});

it("should return correct accessibilityInfo object 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.exist;
expect(avatar.accessibilityInfo.role).to.equal("img");
expect(avatar.accessibilityInfo.type).to.equal("Image");
expect(avatar.accessibilityInfo.description).to.equal("Avatar JD");
});
});

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 +565,4 @@ describe("Avatar Rendering and Interaction", () => {
cy.get("@clickStub")
.should("have.been.calledOnce");
});
});
});
17 changes: 15 additions & 2 deletions 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 All @@ -17,7 +17,11 @@ import type { IAvatarGroupItem } from "./AvatarGroup.js";
// Template
import AvatarTemplate from "./AvatarTemplate.js";

import { AVATAR_TOOLTIP } from "./generated/i18n/i18n-defaults.js";
import {
AVATAR_TOOLTIP,
AVATAR_TYPE_BUTTON,
AVATAR_TYPE_IMAGE,
} from "./generated/i18n/i18n-defaults.js";

// Styles
import AvatarCss from "./generated/themes/Avatar.css.js";
Expand Down Expand Up @@ -493,6 +497,15 @@ class Avatar extends UI5Element implements ITabbable, IAvatarGroupItem {
}
this._imageLoadError = true;
}

get accessibilityInfo() {
return {
role: this._role as AriaRole,
type: this.interactive ? Avatar.i18nBundle.getText(AVATAR_TYPE_BUTTON) : Avatar.i18nBundle.getText(AVATAR_TYPE_IMAGE),
description: this.accessibleNameText,
disabled: this.disabled,
};
}
}

Avatar.define();
Expand Down
6 changes: 6 additions & 0 deletions packages/main/src/i18n/messagebundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ ARIA_ROLEDESCRIPTION_INTERACTIVE_CARD_HEADER=Interactive Card Header
#XACT: ARIA announcement for the Avatar default tooltip
AVATAR_TOOLTIP=Avatar

#XACT: ARIA type description for interactive Avatar (when the Avatar is a button)
AVATAR_TYPE_BUTTON=Button

#XACT: ARIA type description for non-interactive Avatar (when the Avatar is an image)
AVATAR_TYPE_IMAGE=Image

#XACT: ARIA announcement for the Avatar default tooltip
AVATAR_GROUP_DISPLAYED_HIDDEN_LABEL={0} displayed, {1} hidden.

Expand Down
Loading