Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit cf45654

Browse files
aprigoginKenneth G. Franqueiro
authored andcommitted
fix(checkbox): add aria-checked=mixed to indeterminate state (#2389)
BREAKING CHANGE: Adds setNativeControlAttr and removeNativeControlAttr adapter APIs.
1 parent f59b109 commit cf45654

File tree

4 files changed

+38
-3
lines changed

4 files changed

+38
-3
lines changed

packages/mdc-checkbox/adapter.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ class MDCCheckboxAdapter {
4343
/** @param {string} className */
4444
removeClass(className) {}
4545

46+
/**
47+
* Sets an attribute with a given value on the input element.
48+
* @param {string} attr
49+
* @param {string} value
50+
*/
51+
setNativeControlAttr(attr, value) {}
52+
53+
/**
54+
* Removes an attribute from the input element.
55+
* @param {string} attr
56+
*/
57+
removeNativeControlAttr(attr) {}
58+
4659
/** @param {!EventListener} handler */
4760
registerAnimationEndHandler(handler) {}
4861

packages/mdc-checkbox/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ const strings = {
3939
TRANSITION_STATE_CHECKED: 'checked',
4040
TRANSITION_STATE_UNCHECKED: 'unchecked',
4141
TRANSITION_STATE_INDETERMINATE: 'indeterminate',
42+
ARIA_CHECKED_ATTR: 'aria-checked',
43+
ARIA_CHECKED_INDETERMINATE_VALUE: 'mixed',
4244
};
4345

4446
/** @enum {number} */

packages/mdc-checkbox/foundation.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class MDCCheckboxFoundation extends MDCFoundation {
4949
return /** @type {!MDCCheckboxAdapter} */ ({
5050
addClass: (/* className: string */) => {},
5151
removeClass: (/* className: string */) => {},
52+
setNativeControlAttr: () => {},
53+
removeNativeControlAttr: () => {},
5254
registerAnimationEndHandler: (/* handler: EventListener */) => {},
5355
deregisterAnimationEndHandler: (/* handler: EventListener */) => {},
5456
registerChangeHandler: (/* handler: EventListener */) => {},
@@ -203,6 +205,14 @@ class MDCCheckboxFoundation extends MDCFoundation {
203205
return;
204206
}
205207

208+
// Ensure aria-checked is set to mixed if checkbox is in indeterminate state.
209+
if (this.isIndeterminate()) {
210+
this.adapter_.setNativeControlAttr(
211+
strings.ARIA_CHECKED_ATTR, strings.ARIA_CHECKED_INDETERMINATE_VALUE);
212+
} else {
213+
this.adapter_.removeNativeControlAttr(strings.ARIA_CHECKED_ATTR);
214+
}
215+
206216
// Check to ensure that there isn't a previously existing animation class, in case for example
207217
// the user interacted with the checkbox before the animation was finished.
208218
if (this.currentAnimationClass_.length > 0) {

test/unit/mdc-checkbox/foundation.test.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ test('exports numbers', () => {
110110

111111
test('defaultAdapter returns a complete adapter implementation', () => {
112112
verifyDefaultAdapter(MDCCheckboxFoundation, [
113-
'addClass', 'removeClass', 'registerAnimationEndHandler', 'deregisterAnimationEndHandler',
114-
'registerChangeHandler', 'deregisterChangeHandler', 'getNativeControl', 'forceLayout',
115-
'isAttachedToDOM',
113+
'addClass', 'removeClass', 'setNativeControlAttr', 'removeNativeControlAttr', 'registerAnimationEndHandler',
114+
'deregisterAnimationEndHandler', 'registerChangeHandler', 'deregisterChangeHandler', 'getNativeControl',
115+
'forceLayout', 'isAttachedToDOM',
116116
]);
117117
});
118118

@@ -424,6 +424,16 @@ test('change handler triggers layout for changes within the same frame to correc
424424
td.verify(mockAdapter.forceLayout());
425425
});
426426

427+
test('change handler updates aria-checked attribute correctly.', () => {
428+
const {mockAdapter, change} = setupChangeHandlerTest();
429+
430+
change({checked: true, indeterminate: true});
431+
td.verify(mockAdapter.setNativeControlAttr('aria-checked', 'mixed'));
432+
433+
change({checked: true, indeterminate: false});
434+
td.verify(mockAdapter.removeNativeControlAttr('aria-checked'));
435+
});
436+
427437
test('change handler does not add animation classes when isAttachedToDOM() is falsy', () => {
428438
const {mockAdapter, change} = setupChangeHandlerTest();
429439
const animClassArg = td.matchers.argThat((cls) => cls.indexOf('mdc-checkbox--anim') >= 0);

0 commit comments

Comments
 (0)