Skip to content

Commit

Permalink
feat(ui5-dynamic-side-content): add customizable aria labels (#10416)
Browse files Browse the repository at this point in the history
Until now the **Dynamic Side Content** component (`<ui5-dynamic-side-content>`) had `role` with value **complementary** and fixed translatable `aria-label` only for its **Side Content** area.

With this PR is intruduced new property `accessibilityAttributes` that can be used for setting of custom `aria-label` texts for both **Main Content** and **Side Content** areas. Also, a `role` attribute with value **main** and a fixed translatable label is provided for the **Main Content** as a fallback if there is no custom label defined.

There are tests added for the new feature.

Fixes: #8612
  • Loading branch information
NHristov-sap authored Jan 6, 2025
1 parent 7b9205c commit 5887d29
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 13 deletions.
83 changes: 83 additions & 0 deletions packages/fiori/cypress/specs/DynamicSideContent.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { html } from "lit";
import "../../src/DynamicSideContent.js";
import type DynamicSideContent from "../../src/DynamicSideContent.js";

describe("Accessibility", () => {
it("tests main and side content roles", () => {
cy.mount(html`
<ui5-dynamic-side-content>
<div>
<h1>Main Content</h1>
</div>
<div slot="sideContent">
<h1>Side Content</h1>
</div>
</ui5-dynamic-side-content>
`);

cy.get("[ui5-dynamic-side-content]")
.as("dsc");

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-main")
.should("have.attr", "role", "main");

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-side")
.should("have.attr", "role", "complementary");
});

it("tests main and side content aria-label values", () => {
const customMainContentLabel = "Custom Main Content Label";
const customSideContentLabel = "Custom Side Content Label";

cy.mount(html`
<ui5-dynamic-side-content>
<div>
<h1>Main Content</h1>
<ui5-button>Set Custom ARIA Labels</ui5-button>
</div>
<div slot="sideContent">
<h1>Side Content</h1>
</div>
</ui5-dynamic-side-content>
`);

cy.get("[ui5-dynamic-side-content]")
.as("dsc");

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-main")
.should("have.attr", "aria-label", "Main Content");

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-side")
.should("have.attr", "aria-label", "Side Content");

cy.get<DynamicSideContent>("@dsc")
.then($dsc => {
$dsc.get(0).accessibilityAttributes = {
"mainContent": {
"ariaLabel": customMainContentLabel,
},
"sideContent": {
"ariaLabel": customSideContentLabel,
},
};
});

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-main")
.should("have.attr", "aria-label", customMainContentLabel);

cy.get("@dsc")
.shadow()
.find(".ui5-dsc-side")
.should("have.attr", "aria-label", customSideContentLabel);
});
});
35 changes: 33 additions & 2 deletions packages/fiori/src/DynamicSideContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ import SideContentPosition from "./types/SideContentPosition.js";
import SideContentVisibility from "./types/SideContentVisibility.js";
import SideContentFallDown from "./types/SideContentFallDown.js";
import DynamicSideContentTemplate from "./DynamicSideContentTemplate.js";
import type {
AccessibilityAttributes,
} from "@ui5/webcomponents-base";

// Styles
import DynamicSideContentCss from "./generated/themes/DynamicSideContent.css.js";

// Texts
import {
DSC_MAIN_ARIA_LABEL,
DSC_SIDE_ARIA_LABEL,
} from "./generated/i18n/i18n-defaults.js";

Expand All @@ -34,6 +38,12 @@ type DynamicSideContentLayoutChangeEventDetail = {
sideContentVisible: boolean,
}

type DynamicSideContentAriaAccessibilityAttributes = Pick<AccessibilityAttributes, "ariaLabel">;
type DynamicSideContentAccessibilityAttributes = {
mainContent?: DynamicSideContentAriaAccessibilityAttributes,
sideContent?: DynamicSideContentAriaAccessibilityAttributes,
}

/**
* @class
*
Expand Down Expand Up @@ -186,6 +196,21 @@ class DynamicSideContent extends UI5Element {
@property({ type: Boolean })
equalSplit = false;

/**
* Defines additional accessibility attributes on different areas of the component.
*
* The accessibilityAttributes object has the following fields:
*
* - **mainContent**: `mainContent.ariaLabel` defines the aria-label of the main content area. Accepts any string.
* - **sideContent**: `sideContent.ariaLabel` defines the aria-label of the side content area. Accepts any string.
*
* @default {}
* @public
* @since 2.6.0
*/
@property({ type: Object })
accessibilityAttributes: DynamicSideContentAccessibilityAttributes = {};

/**
* @private
*/
Expand Down Expand Up @@ -285,9 +310,14 @@ class DynamicSideContent extends UI5Element {
};
}

get accInfo() {
get accInfo(): DynamicSideContentAccessibilityAttributes {
return {
"label": DynamicSideContent.i18nBundle.getText(DSC_SIDE_ARIA_LABEL),
mainContent: {
ariaLabel: this.accessibilityAttributes.mainContent?.ariaLabel || DynamicSideContent.i18nBundle.getText(DSC_MAIN_ARIA_LABEL),
},
sideContent: {
ariaLabel: this.accessibilityAttributes.sideContent?.ariaLabel || DynamicSideContent.i18nBundle.getText(DSC_SIDE_ARIA_LABEL),
},
};
}

Expand Down Expand Up @@ -462,4 +492,5 @@ DynamicSideContent.define();
export default DynamicSideContent;
export type {
DynamicSideContentLayoutChangeEventDetail,
DynamicSideContentAccessibilityAttributes,
};
4 changes: 3 additions & 1 deletion packages/fiori/src/DynamicSideContentTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export default function DynamicSideContentTemplate(this: DynamicSideContent) {
function mainContent(this: DynamicSideContent) {
return (
<div
role="main"
aria-label={this.accInfo.mainContent?.ariaLabel}
class={this.classes.main}
style={this.styles.main}
>
Expand All @@ -36,7 +38,7 @@ function sideContent(this: DynamicSideContent) {
return (
<aside
role="complementary"
aria-label={this.accInfo.label}
aria-label={this.accInfo.sideContent?.ariaLabel}
class={this.classes.side}
style={this.styles.side}
>
Expand Down
3 changes: 3 additions & 0 deletions packages/fiori/src/i18n/messagebundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ IM_TITLE_SURVEY=Your Opinion Matters
#XTIT: IllustratedMessage's subtitle for the Survey illustration
IM_SUBTITLE_SURVEY=We want to hear what you think about SAP software. Share your feedback with us by taking our short survey.

#XACT: ARIA announcement for DynamicSideContent main content label
DSC_MAIN_ARIA_LABEL=Main Content

#XACT: ARIA announcement for DynamicSideContent side content label
DSC_SIDE_ARIA_LABEL=Side Content

Expand Down
9 changes: 9 additions & 0 deletions packages/fiori/test/pages/DynamicSideContent.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ <h1>Side Content</h1>
mainVisible.value = event.detail.mainContentVisible ? "1" : "0"
sideVisible.value = event.detail.sideContentVisible ? "1" : "0"
});

dynamicSideContent.accessibilityAttributes = {
mainContent: {
ariaLabel: "Main Content Area",
},
sideContent: {
ariaLabel: "Side Content Area",
}
};
</script>

</body>
Expand Down
10 changes: 0 additions & 10 deletions packages/fiori/test/specs/DynamicSideContent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,4 @@ describe("'layout-change' event: ", () => {
assert.strictEqual(await mainVisible.getValue(), "1", "The event returns correct main content visibility");
assert.strictEqual(await sideVisible.getValue(), "1", "The event returns correct side content visibility");
});
});

describe("ARIA attributes: ", () => {
it("exist", async () => {
await browser.url(`test/pages/DynamicSideContent.html`);
const dynamicSideContent = await browser.$("ui5-dynamic-side-content");

assert.strictEqual(await dynamicSideContent.shadow$(".ui5-dsc-side").getAttribute("aria-label"), "Side Content", "'aria-label' attribute is set correctly");
assert.strictEqual(await dynamicSideContent.shadow$(".ui5-dsc-side").getAttribute("role"), "complementary", "'role' attribute is set correctly");
});
});

0 comments on commit 5887d29

Please sign in to comment.