feat(switch): Switch now supports label activation by setting formAssociated.

PiperOrigin-RevId: 495993033
This commit is contained in:
Material Web Team 2022-12-16 17:06:12 -08:00 committed by Copybara-Service
parent 3f6070ea31
commit 7473f4647d
2 changed files with 36 additions and 5 deletions

View File

@ -15,6 +15,7 @@ import {ClassInfo, classMap} from 'lit/directives/class-map.js';
import {ifDefined} from 'lit/directives/if-defined.js';
import {ActionElement, BeginPressConfig, EndPressConfig} from '../../actionelement/action-element.js';
import {isActivationClick} from '../../controller/events.js';
import {FormController, getFormValue} from '../../controller/form-controller.js';
import {ariaProperty} from '../../decorators/aria-property.js';
import {pointerPress as focusRingPointerPress, shouldShowStrongFocus} from '../../focus/strong-focus.js';
@ -30,6 +31,8 @@ export class Switch extends ActionElement {
static override shadowRootOptions:
ShadowRootInit = {mode: 'open', delegatesFocus: true};
static formAssociated = true;
/**
* Disables the switch and makes it non-interactive.
*/
@ -65,7 +68,9 @@ export class Switch extends ActionElement {
// Ripple
@query('md-ripple') readonly ripple!: MdRipple;
// FormController
/**
* The associated form element with which this element's value will submit.
*/
get form() {
return this.closest('form');
}
@ -88,12 +93,17 @@ export class Switch extends ActionElement {
constructor() {
super();
this.addController(new FormController(this));
this.addEventListener('click', (event: MouseEvent) => {
if (!isActivationClick(event)) {
return;
}
this.button?.focus();
this.endPress({cancelled: false});
});
}
override click() {
this.endPress({cancelled: false});
super.click();
}
// Button
@query('button', true) private readonly button!: HTMLButtonElement|null;
protected override render(): TemplateResult {
const ariaLabelValue = this.ariaLabel ? this.ariaLabel : undefined;

View File

@ -39,6 +39,12 @@ function renderSwitchInForm(propsInit: Partial<TestSwitch> = {}) {
`;
}
function renderSwitchInLabel(propsInit: Partial<TestSwitch> = {}) {
return html`
<label>${renderSwitch(propsInit)}</label>
`;
}
describe('md-switch', () => {
const env = new Environment();
@ -227,5 +233,20 @@ describe('md-switch', () => {
const formData = await harness.submitForm();
expect(formData.get('foo')).toEqual('bar');
});
describe('label activation', () => {
let label: HTMLLabelElement;
it('toggles when label is clicked', async () => {
toggle = await switchElement({}, renderSwitchInLabel);
label = toggle.parentElement as HTMLLabelElement;
label.click();
await env.waitForStability();
expect(toggle.selected).toBeTrue();
label.click();
await env.waitForStability();
expect(toggle.selected).toBeFalse();
});
});
});
});