From 54a1c86d6a5d533b0c8c2d18edc62454a7c17bab Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Thu, 23 Oct 2025 10:09:05 -0700 Subject: [PATCH] fix(checkbox, toggle): fire ionFocus and ionBlur (#30733) Issue number: internal --------- ## What is the current behavior? `ionFocus` and `ionBlur` are not being emitted for checkbox and toggle. ## What is the new behavior? - Moved the `onFocus` and `onBlur` to `Host` - Added tests for `onFocus`, `onBlur`, and `onChange`. - Added a workaround on Playwright in order to trigger `ionBlur` since Playwright browsers aren't acting like native browsers when it comes to tabbing. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `8.7.7-dev.11761071592.1d1b804d` --------- Co-authored-by: ionitron Co-authored-by: Shane --- core/src/components/checkbox/checkbox.tsx | 13 +- .../checkbox/test/basic/checkbox.e2e.ts | 196 +++++++++++++- ...kbox-focus-ios-ltr-Mobile-Chrome-linux.png | Bin 0 -> 2018 bytes ...box-focus-ios-ltr-Mobile-Firefox-linux.png | Bin 0 -> 2442 bytes ...kbox-focus-ios-ltr-Mobile-Safari-linux.png | Bin 0 -> 2849 bytes ...item-focus-ios-ltr-Mobile-Chrome-linux.png | Bin 0 -> 2090 bytes ...tem-focus-ios-ltr-Mobile-Firefox-linux.png | Bin 0 -> 2779 bytes ...item-focus-ios-ltr-Mobile-Safari-linux.png | Bin 0 -> 2697 bytes .../components/checkbox/test/basic/index.html | 14 + .../components/checkbox/test/item/index.html | 14 + .../components/toggle/test/basic/index.html | 14 + .../toggle/test/basic/toggle.e2e.ts | 251 +++++++++++++++++- ...ggle-focus-ios-ltr-Mobile-Chrome-linux.png | Bin 0 -> 2390 bytes ...gle-focus-ios-ltr-Mobile-Firefox-linux.png | Bin 0 -> 2967 bytes ...ggle-focus-ios-ltr-Mobile-Safari-linux.png | Bin 0 -> 3396 bytes ...item-focus-ios-ltr-Mobile-Chrome-linux.png | Bin 0 -> 2507 bytes ...tem-focus-ios-ltr-Mobile-Firefox-linux.png | Bin 0 -> 3253 bytes ...item-focus-ios-ltr-Mobile-Safari-linux.png | Bin 0 -> 3158 bytes .../components/toggle/test/item/index.html | 14 + core/src/components/toggle/toggle.tsx | 11 +- .../playwright/page/utils/spy-on-event.ts | 34 +++ 21 files changed, 542 insertions(+), 19 deletions(-) create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Chrome-linux.png create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Firefox-linux.png create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Safari-linux.png create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Chrome-linux.png create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Firefox-linux.png create mode 100644 core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Safari-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-focus-ios-ltr-Mobile-Chrome-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-focus-ios-ltr-Mobile-Firefox-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-focus-ios-ltr-Mobile-Safari-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-in-item-focus-ios-ltr-Mobile-Chrome-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-in-item-focus-ios-ltr-Mobile-Firefox-linux.png create mode 100644 core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-in-item-focus-ios-ltr-Mobile-Safari-linux.png diff --git a/core/src/components/checkbox/checkbox.tsx b/core/src/components/checkbox/checkbox.tsx index 00a9de5c7c..22f3959fba 100644 --- a/core/src/components/checkbox/checkbox.tsx +++ b/core/src/components/checkbox/checkbox.tsx @@ -34,7 +34,6 @@ export class Checkbox implements ComponentInterface { private inputLabelId = `${this.inputId}-lbl`; private helperTextId = `${this.inputId}-helper-text`; private errorTextId = `${this.inputId}-error-text`; - private focusEl?: HTMLElement; private inheritedAttributes: Attributes = {}; @Element() el!: HTMLIonCheckboxElement; @@ -147,9 +146,7 @@ export class Checkbox implements ComponentInterface { /** @internal */ @Method() async setFocus() { - if (this.focusEl) { - this.focusEl.focus(); - } + this.el.focus(); } /** @@ -169,7 +166,6 @@ export class Checkbox implements ComponentInterface { private toggleChecked = (ev: Event) => { ev.preventDefault(); - this.setFocus(); this.setChecked(!this.checked); this.indeterminate = false; }; @@ -285,6 +281,9 @@ export class Checkbox implements ComponentInterface { aria-disabled={disabled ? 'true' : null} tabindex={disabled ? undefined : 0} onKeyDown={this.onKeyDown} + onFocus={this.onFocus} + onBlur={this.onBlur} + onClick={this.onClick} class={createColorClasses(color, { [mode]: true, 'in-item': hostContext('ion-item', el), @@ -296,7 +295,6 @@ export class Checkbox implements ComponentInterface { [`checkbox-alignment-${alignment}`]: alignment !== undefined, [`checkbox-label-placement-${labelPlacement}`]: true, })} - onClick={this.onClick} >