Skip to content

Commit b43f56e

Browse files
authored
feat(ui5-switch): accessibility is enhanced for readonly state. (#13367)
When component is in readonly state an aria-describedBy attribute is added referencing a hidden html element, because the screen readers does not announce aria-readonly attribute.
1 parent e4fba6a commit b43f56e

4 files changed

Lines changed: 40 additions & 2 deletions

File tree

packages/main/cypress/specs/Switch.cy.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,30 @@ describe("General accesibility attributes", () => {
191191
cy.get("[ui5-switch]")
192192
.ui5SwitchCheckAttributeInShadowDomRoot("aria-required", "false");
193193
});
194+
195+
it("Should have 'aria-describedby' attribute when readonly", () => {
196+
cy.mount(<Switch readonly></Switch>);
197+
198+
cy.get("[ui5-switch]")
199+
.then($switch => {
200+
const switchId = ($switch.get(0) as Switch)._id;
201+
const expectedDescribedBy = `${switchId}-readonly-desc`;
202+
203+
cy.wrap($switch)
204+
.ui5SwitchCheckAttributeInShadowDomRoot("aria-describedby", expectedDescribedBy);
205+
});
206+
});
207+
208+
it("Should not have 'aria-describedby' attribute when not readonly", () => {
209+
cy.mount(<Switch></Switch>);
210+
211+
cy.mount(<Switch></Switch>);
212+
213+
cy.get("[ui5-switch]")
214+
.shadow()
215+
.find(".ui5-switch-root")
216+
.should("not.have.attr", "aria-describedby");
217+
});
194218
});
195219

196220
describe("General interactions in form", () => {

packages/main/src/Switch.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
FORM_CHECKABLE_REQUIRED,
2020
SWITCH_ON,
2121
SWITCH_OFF,
22+
ACC_STATE_READONLY,
2223
} from "./generated/i18n/i18n-defaults.js";
2324

2425
// Template
@@ -364,6 +365,14 @@ class Switch extends UI5Element implements IFormInputElement {
364365
get ariaLabelText() {
365366
return getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || undefined;
366367
}
368+
369+
get ariaDescribedBy() {
370+
return this.readonly ? `${this._id}-readonly-desc` : undefined;
371+
}
372+
373+
get ariaDescribedByText() {
374+
return this.readonly ? Switch.i18nBundle.getText(ACC_STATE_READONLY) : "";
375+
}
367376
}
368377

369378
Switch.define();

packages/main/src/SwitchTemplate.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default function SwitchTemplate(this: Switch) {
2222
aria-disabled={this.effectiveAriaDisabled}
2323
aria-readonly={this.effectiveAriaReadonly}
2424
aria-required={this.required}
25+
aria-describedby={this.ariaDescribedBy}
2526
onClick={this._onclick}
2627
onKeyUp={this._onkeyup}
2728
onKeyDown={this._onkeydown}
@@ -61,6 +62,8 @@ export default function SwitchTemplate(this: Switch) {
6162
</>
6263
}
6364

65+
{this.readonly && <span class="ui5-switch-text ui5-switch-text--readonly" id={this.ariaDescribedBy} aria-hidden={this._textAriaHidden}>{this.ariaDescribedByText}</span>}
66+
6467
<span class="ui5-switch-handle" part="handle"></span>
6568
</div>
6669
</div>

packages/main/src/themes/Switch.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,12 @@
145145
cursor: default;
146146
}
147147

148-
.ui5-switch-root.ui5-switch--checked .ui5-switch-text--off {
148+
.ui5-switch-root.ui5-switch--checked .ui5-switch-text--off,
149+
.ui5-switch-root.ui5-switch--checked .ui5-switch-text--readonly {
149150
visibility: var(--_ui5_switch_text_hidden);
150151
}
151-
.ui5-switch-root:not(.ui5-switch--checked) .ui5-switch-text--on {
152+
.ui5-switch-root:not(.ui5-switch--checked) .ui5-switch-text--on,
153+
.ui5-switch-root:not(.ui5-switch--checked) .ui5-switch-text--readonly {
152154
visibility: var(--_ui5_switch_text_hidden);
153155
}
154156

0 commit comments

Comments
 (0)