import { ChangeDetectionStrategy, Component, input, model } from '@angular/core'; import { uniqueId } from '../core/a11y'; import { AuFormControl, provideValueAccessor } from '../core/form-control'; /** * On/off switch (WAI-ARIA switch pattern): a native button with role="switch" and * aria-checked, so Enter and Space both toggle it and the label is clickable. */ @Component({ selector: 'au-switch', changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideValueAccessor(() => AuSwitch)], template: ` @if (hint()) { {{ hint() }} } `, styles: ` :host { display: inline-flex; align-items: flex-start; gap: 0.65rem; font-family: var(--au-font); color: var(--au-text); } .au-switch__control { flex: none; position: relative; width: 2.6rem; height: 1.5rem; padding: 0; cursor: pointer; border: 1.5px solid var(--au-border-strong); border-radius: 999px; background: var(--au-surface-2); transition: background var(--au-duration), border-color var(--au-duration); } .au-switch__thumb { position: absolute; top: 50%; left: 0.15rem; width: 1.05rem; height: 1.05rem; border-radius: 50%; background: var(--au-border-strong); transform: translateY(-50%); transition: left var(--au-duration), background var(--au-duration); } .au-switch__control[aria-checked='true'] { background: var(--au-accent); border-color: var(--au-accent); } .au-switch__control[aria-checked='true'] .au-switch__thumb { left: calc(100% - 1.2rem); background: var(--au-accent-contrast); } .au-switch__control:focus-visible { outline: 2px solid var(--au-focus); outline-offset: 2px; } .au-switch__control:disabled { opacity: 0.55; cursor: not-allowed; } .au-switch__text { display: grid; gap: 0.1rem; line-height: 1.5rem; } .au-switch__label { cursor: pointer; } .au-switch__hint { font-size: 0.8rem; line-height: 1.3; color: var(--au-muted); } `, }) export class AuSwitch extends AuFormControl { readonly value = model(false); protected readonly emptyValue = false; readonly hint = input(''); readonly buttonId = uniqueId('au-switch'); protected readonly labelId = `${this.buttonId}-label`; protected readonly hintId = `${this.buttonId}-hint`; protected toggle(): void { if (!this.isDisabled()) this.commit(!this.value()); } }