Skip to content
Draft
129 changes: 126 additions & 3 deletions packages/fiori/cypress/specs/IllustratedMessage.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ describe("Accessibility", () => {

cy.get("[ui5-illustrated-message]")
.shadow()
.find("svg")
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "role", "presentation");

cy.get("[ui5-illustrated-message]")
.shadow()
.find("svg")
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "aria-hidden", "true");
});

Expand All @@ -30,10 +30,133 @@ describe("Accessibility", () => {

cy.get("[ui5-illustrated-message]")
.shadow()
.find("svg")
.find(".ui5-illustrated-message-illustration")
.should("not.have.attr", "aria-label");

});

it("should have role=img and aria-label with illustration name when decorative is false", () => {
cy.mount(
<IllustratedMessage name="UnableToUpload" decorative={false}>
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "role", "img");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "aria-label", "UnableToUpload");
});

it("should have role=img and aria-label with illustration name by default (when decorative is not set)", () => {
cy.mount(
<IllustratedMessage name="NoData">
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "role", "img");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-illustration")
.should("have.attr", "aria-label", "NoData");
});

it("should have proper role and aria-label on the root container", () => {
cy.mount(
<IllustratedMessage name="UnableToUpload">
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should("have.attr", "role", "region");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should("have.attr", "aria-label", "Illustrated Message");
});

it("should have aria-describedby pointing to the title element", () => {
cy.mount(
<IllustratedMessage name="UnableToUpload">
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should("have.attr", "aria-describedby")
.and("match", /-im-title$/);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-title")
.should("have.attr", "id")
.and("match", /-im-title$/);

// Verify that aria-describedby points to the correct title element
cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.invoke("attr", "aria-describedby")
.then((ariaDescribedBy) => {
cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-title")
.should("have.attr", "id", ariaDescribedBy);
});
});

it("should maintain accessibility attributes when title is present", () => {
cy.mount(
<IllustratedMessage name="UnableToUpload" titleText="Custom Title">
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should("have.attr", "role", "region")
.and("have.attr", "aria-label", "Illustrated Message")
.and("have.attr", "aria-describedby");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-title")
.should("exist")
.and("have.attr", "id");
});

it("should maintain accessibility attributes when title is slotted", () => {
cy.mount(
<IllustratedMessage name="UnableToUpload">
<div slot="title">Slotted Title</div>
</IllustratedMessage>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should("have.attr", "role", "region")
.and("have.attr", "aria-label", "Illustrated Message")
.and("have.attr", "aria-describedby");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-title")
.should("exist")
.and("have.attr", "id");
});
});

describe("design", () => {
Expand Down
28 changes: 0 additions & 28 deletions packages/fiori/src/IllustratedMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,30 +421,6 @@ class IllustratedMessage extends UI5Element {
}
}

_setSVGAccAttrs() {
const svg = this.shadowRoot!.querySelector(".ui5-illustrated-message-illustration svg");

if (!svg) {
return;
}

if (this.decorative) {
svg.setAttribute("role", "presentation");
svg.setAttribute("aria-hidden", "true");
svg.removeAttribute("aria-label");
} else {
svg.removeAttribute("role");
svg.removeAttribute("aria-hidden");

// Set aria-label only when not decorative and text exists
if (this.ariaLabelText) {
svg.setAttribute("aria-label", this.ariaLabelText);
} else {
svg.removeAttribute("aria-label");
}
}
}

_adjustHeightToFitContainer() {
const illustrationWrapper = <HTMLElement> this.shadowRoot!.querySelector(".ui5-illustrated-message-illustration"),
illustration = illustrationWrapper.querySelector("svg");
Expand All @@ -458,10 +434,6 @@ class IllustratedMessage extends UI5Element {
}
}

onAfterRendering() {
this._setSVGAccAttrs();
}

/**
* Modifies the IM styles in accordance to the `size` property's value.
* Note: The resize handler has no effect when size is different than "Auto".
Expand Down
12 changes: 9 additions & 3 deletions packages/fiori/src/IllustratedMessageTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import type IllustratedMessage from "./IllustratedMessage.js";

export default function IllustratedMessageTemplate(this: IllustratedMessage) {
return (
<div class="ui5-illustrated-message-root">
<div role="region"
aria-label="Illustrated Message"
aria-describedby={`${this._id}-im-title`}
class="ui5-illustrated-message-root">
<div class="ui5-illustrated-message-inner">
<div class="ui5-illustrated-message-illustration">
<div class="ui5-illustrated-message-illustration"
role={this.decorative ? "presentation" : "img"}
aria-hidden={this.decorative}
aria-label={!this.decorative ? this.name : undefined}>
{renderIllustration.call(this)}
</div>
<div class="ui5-illustrated-message-text-and-actions-container">
{this.hasTitle &&
<div part="title" class="ui5-illustrated-message-title">
<div part="title" id={`${this._id}-im-title`} class="ui5-illustrated-message-title">
{this.hasFormattedTitle ?
<slot name="title"></slot>
:
Expand Down
Loading