Skip to content

Commit

Permalink
chore: Adds aria support for the switch
Browse files Browse the repository at this point in the history
  • Loading branch information
rowa-audil authored and Yngrid Coello committed Nov 9, 2020
1 parent 43712bf commit 3bec04c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
36 changes: 36 additions & 0 deletions libs/fluid-elements/switch/src/lib/switch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,42 @@ describe('Fluid switch', () => {
});
});

describe('aria-checked attribute', () => {
it('should have aria-checked set to false by default', () => {
expect(fixture.hasAttribute('aria-checked')).toBeTruthy();
expect(fixture.getAttribute('aria-checked')).toBe('false');
});

it('should have aria-checked set to false when the switch is not checked', async () => {
fixture.checked = false;
await tick();
expect(fixture.hasAttribute('aria-checked')).toBeTruthy();
expect(fixture.getAttribute('aria-checked')).toBe('false');
});

it('should have aria-checked set to true when the switch is checked', async () => {
fixture.checked = true;
await tick();
expect(fixture.hasAttribute('aria-checked')).toBeTruthy();
expect(fixture.getAttribute('aria-checked')).toBe('true');
});

it('should have aria-checked set to true when the switch is clicked', async () => {
const label = fixture.shadowRoot?.querySelector('label');
label?.click();
await tick();
expect(fixture.hasAttribute('aria-checked')).toBeTruthy();
expect(fixture.getAttribute('aria-checked')).toBe('true');
});
it('should have aria-checked set to true when the switch is focused and space is pressed', async () => {
const checkbox = fixture.shadowRoot?.querySelector('svg');
dispatchKeyboardEvent(checkbox!, 'keyup', SPACE);
await tick();
expect(fixture.hasAttribute('aria-checked')).toBeTruthy();
expect(fixture.getAttribute('aria-checked')).toBe('true');
});
});

describe('disabled attribute', () => {
it('should set the disabled state when the attribute is present', async () => {
fixture.setAttribute('disabled', '');
Expand Down
43 changes: 41 additions & 2 deletions libs/fluid-elements/switch/src/lib/switch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let uniqueCounter = 0;
export class FluidSwitch extends LitElement {
/**
* Unique identifier used for the id and label connection
* within the checkbox.
* within the switch.
*/
private _unique = `fluid-switch-${uniqueCounter++}`;

Expand Down Expand Up @@ -89,7 +89,7 @@ export class FluidSwitch extends LitElement {
display: flex;
position: relative;
}
:host([disabled]) .fluid-switch-input, /* Checkbox should be hidden in the disabled state as well. */
:host([disabled]) .fluid-switch-input, /* Switch should be hidden in the disabled state as well. */
.fluid-switch-input {
position: absolute;
width: 35px;
Expand Down Expand Up @@ -193,12 +193,51 @@ export class FluidSwitch extends LitElement {
}
private _checked = false;

/**
* Role of the switch.
* @private - An internal prop that should not appear in the readme and should
* not be set by the outside.
*/
@property({
type: String,
reflect: true,
})
role: string = 'switch';

/**
* Aria-checked attribute of the switch.
* @private - An internal prop that should not appear in the readme and should
* not be set by the outside.
*/
@property({
type: String,
reflect: true,
attribute: 'aria-checked',
})
ariaChecked: string = 'false';

/** First updated lifecycle */
firstUpdated(props: Map<string | number | symbol, unknown>): void {
super.firstUpdated(props);
this._inputElement = this.shadowRoot?.querySelector('input')!;
}

/** Update lifecycle */
update(props: Map<string | number | symbol, unknown>): void {
// Aria-checked depends on the value of checked, but is never actually
// set by the litElement reactivity. In the updated lifeCycle
// we need to manually update the ariaChecked attribute here.
if (props.has('checked')) {
this.ariaChecked = this.checked.toString();
}
// Changing the aria-checked or any observed property in the update, will
// add it to the updated properties. When calling super first in, the change
// of properties in the update call will trigger an update, as the properties
// will have changed after the super.update() call. To prevent an additional
// cycle, we make the modifications before calling the super lifecycle
super.update(props);
}

/**
* Render function.
*/
Expand Down

0 comments on commit 3bec04c

Please sign in to comment.