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

Commit

Permalink
fix(checkbox): add aria-checked=mixed to indeterminate state (#2389)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Adds setNativeControlAttr and removeNativeControlAttr adapter APIs.
  • Loading branch information
aprigogin authored and Kenneth G. Franqueiro committed Mar 13, 2018
1 parent f59b109 commit cf45654
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 3 deletions.
13 changes: 13 additions & 0 deletions packages/mdc-checkbox/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ class MDCCheckboxAdapter {
/** @param {string} className */
removeClass(className) {}

/**
* Sets an attribute with a given value on the input element.
* @param {string} attr
* @param {string} value
*/
setNativeControlAttr(attr, value) {}

/**
* Removes an attribute from the input element.
* @param {string} attr
*/
removeNativeControlAttr(attr) {}

/** @param {!EventListener} handler */
registerAnimationEndHandler(handler) {}

Expand Down
2 changes: 2 additions & 0 deletions packages/mdc-checkbox/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const strings = {
TRANSITION_STATE_CHECKED: 'checked',
TRANSITION_STATE_UNCHECKED: 'unchecked',
TRANSITION_STATE_INDETERMINATE: 'indeterminate',
ARIA_CHECKED_ATTR: 'aria-checked',
ARIA_CHECKED_INDETERMINATE_VALUE: 'mixed',
};

/** @enum {number} */
Expand Down
10 changes: 10 additions & 0 deletions packages/mdc-checkbox/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class MDCCheckboxFoundation extends MDCFoundation {
return /** @type {!MDCCheckboxAdapter} */ ({
addClass: (/* className: string */) => {},
removeClass: (/* className: string */) => {},
setNativeControlAttr: () => {},
removeNativeControlAttr: () => {},
registerAnimationEndHandler: (/* handler: EventListener */) => {},
deregisterAnimationEndHandler: (/* handler: EventListener */) => {},
registerChangeHandler: (/* handler: EventListener */) => {},
Expand Down Expand Up @@ -203,6 +205,14 @@ class MDCCheckboxFoundation extends MDCFoundation {
return;
}

// Ensure aria-checked is set to mixed if checkbox is in indeterminate state.
if (this.isIndeterminate()) {
this.adapter_.setNativeControlAttr(
strings.ARIA_CHECKED_ATTR, strings.ARIA_CHECKED_INDETERMINATE_VALUE);
} else {
this.adapter_.removeNativeControlAttr(strings.ARIA_CHECKED_ATTR);
}

// Check to ensure that there isn't a previously existing animation class, in case for example
// the user interacted with the checkbox before the animation was finished.
if (this.currentAnimationClass_.length > 0) {
Expand Down
16 changes: 13 additions & 3 deletions test/unit/mdc-checkbox/foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ test('exports numbers', () => {

test('defaultAdapter returns a complete adapter implementation', () => {
verifyDefaultAdapter(MDCCheckboxFoundation, [
'addClass', 'removeClass', 'registerAnimationEndHandler', 'deregisterAnimationEndHandler',
'registerChangeHandler', 'deregisterChangeHandler', 'getNativeControl', 'forceLayout',
'isAttachedToDOM',
'addClass', 'removeClass', 'setNativeControlAttr', 'removeNativeControlAttr', 'registerAnimationEndHandler',
'deregisterAnimationEndHandler', 'registerChangeHandler', 'deregisterChangeHandler', 'getNativeControl',
'forceLayout', 'isAttachedToDOM',
]);
});

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

test('change handler updates aria-checked attribute correctly.', () => {
const {mockAdapter, change} = setupChangeHandlerTest();

change({checked: true, indeterminate: true});
td.verify(mockAdapter.setNativeControlAttr('aria-checked', 'mixed'));

change({checked: true, indeterminate: false});
td.verify(mockAdapter.removeNativeControlAttr('aria-checked'));
});

test('change handler does not add animation classes when isAttachedToDOM() is falsy', () => {
const {mockAdapter, change} = setupChangeHandlerTest();
const animClassArg = td.matchers.argThat((cls) => cls.indexOf('mdc-checkbox--anim') >= 0);
Expand Down

0 comments on commit cf45654

Please sign in to comment.