From ac6eaae2f25b5a596ada61942599396b253cc660 Mon Sep 17 00:00:00 2001 From: ShaneK Date: Thu, 10 Apr 2025 06:27:19 -0700 Subject: [PATCH 1/3] fix(toggle): ensure proper visual selection when navigating via VoiceOver in Safari --- core/src/components/toggle/toggle.scss | 6 +++- core/src/components/toggle/toggle.tsx | 44 ++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/core/src/components/toggle/toggle.scss b/core/src/components/toggle/toggle.scss index ad78e471c0b..0aec6967d22 100644 --- a/core/src/components/toggle/toggle.scss +++ b/core/src/components/toggle/toggle.scss @@ -69,8 +69,12 @@ pointer-events: none; } +/** + * The native input must be hidden with display instead of visibility or + * aria-hidden to avoid accessibility issues with nested interactive elements. + */ input { - @include visually-hidden(); + display: none; } // Toggle Wrapper diff --git a/core/src/components/toggle/toggle.tsx b/core/src/components/toggle/toggle.tsx index 8ccdb60d3dd..230b427f51a 100644 --- a/core/src/components/toggle/toggle.tsx +++ b/core/src/components/toggle/toggle.tsx @@ -35,6 +35,7 @@ import type { ToggleChangeEventDetail } from './toggle-interface'; }) export class Toggle implements ComponentInterface { private inputId = `ion-tg-${toggleIds++}`; + private inputLabelId = `${this.inputId}-lbl`; private helperTextId = `${this.inputId}-helper-text`; private errorTextId = `${this.inputId}-error-text`; private gesture?: Gesture; @@ -246,6 +247,15 @@ export class Toggle implements ComponentInterface { } } + private onKeyDown = (ev: KeyboardEvent) => { + if (ev.key === ' ') { + ev.preventDefault(); + if (!this.disabled) { + this.toggleChecked(); + } + } + }; + private onClick = (ev: MouseEvent) => { if (this.disabled) { return; @@ -355,8 +365,23 @@ export class Toggle implements ComponentInterface { } render() { - const { activated, color, checked, disabled, el, justify, labelPlacement, inputId, name, alignment, required } = - this; + const { + activated, + alignment, + checked, + color, + disabled, + el, + errorTextId, + hasLabel, + inheritedAttributes, + inputId, + inputLabelId, + justify, + labelPlacement, + name, + required, + } = this; const mode = getIonMode(this); const value = this.getValue(); @@ -365,9 +390,15 @@ export class Toggle implements ComponentInterface { return ( -