Skip to content

fix(checkbox,radio,toggle): add missing keyboard focus indicators - #31295

Merged
ShaneK merged 29 commits into
mainfrom
FW-7585-FW-7586
Jul 31, 2026
Merged

fix(checkbox,radio,toggle): add missing keyboard focus indicators#31295
ShaneK merged 29 commits into
mainfrom
FW-7585-FW-7586

Conversation

@ShaneK

@ShaneK ShaneK commented Jul 24, 2026

Copy link
Copy Markdown
Member

Issue number: internal


What is the current behavior?

Currently, ion-checkbox and ion-toggle never show a keyboard focus indicator. ion-checkbox doesn't set the ion-focusable class and has no focus styles in the ios or md themes, so it can't receive the ion-focused class or render a ring. ion-toggle's only focus rule (:host(.ion-focused) input) targets the native input, which is display: none, so it never renders.

Separately, ion-checkbox, ion-radio, and ion-toggle show no focus indicator inside an ion-item that holds more than one input. ion-checkbox and ion-radio disable their own indicator in an item on the assumption the item draws one, but a multi-input item has no cover to highlight, so nothing is focused.

What is the new behavior?

ion-checkbox now sets ion-focusable when it isn't deferring to an item, with matching ios and md focus styles, so a standalone checkbox shows the same indicator ion-radio already did. Both ion-checkbox and ion-radio also become focusable inside a multi-input item, detected through the item's item-multiple-inputs class, so each control shows its own indicator when the item can't.

ion-toggle always shows its own indicator. Unlike checkbox and radio, it's excluded from the item's input cover, so an item never highlights on its behalf, in or out of a multi-input item. Its dead input focus rule is replaced with a ring on the visible track in both themes.

Does this introduce a breaking change?

  • Yes
  • No

Other information

Preview checkbox:

Preview toggle:

Preview radio:

@ShaneK
ShaneK requested a review from a team as a code owner July 24, 2026 18:01
@ShaneK
ShaneK requested a review from gnbm July 24, 2026 18:01
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ionic-framework Ready Ready Preview Jul 31, 2026 8:40pm

Request Review

@github-actions github-actions Bot added the package: core @ionic/core package label Jul 24, 2026

@brandyscarney brandyscarney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! My main feedback is we should be hiding the browser's native focus ring.

Comment thread core/src/components/radio/radio.tsx
Comment thread core/src/components/checkbox/checkbox.scss
Comment thread core/src/components/toggle/toggle.scss

@brandyscarney brandyscarney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code itself looks great! My requests are just for additional screenshots & some test changes.

Comment thread core/src/components/checkbox/test/item/index.html
Comment thread core/src/components/radio/test/item/index.html Outdated
Comment thread core/src/components/checkbox/test/item/index.html
Comment thread core/src/components/radio/test/item/index.html
Comment thread core/src/components/radio/radio.tsx
Comment thread core/src/components/checkbox/test/basic/checkbox.e2e.ts
Comment thread core/src/components/toggle/test/basic/toggle.e2e.ts
Comment thread core/src/components/checkbox/test/basic/checkbox.e2e.ts
Comment thread core/src/components/checkbox/test/item/checkbox.e2e.ts
Comment thread core/src/components/checkbox/checkbox.ios.scss Outdated
Comment thread core/src/components/checkbox/checkbox.md.scss Outdated
Comment thread core/src/components/checkbox/checkbox.ios.vars.scss Outdated
Comment thread core/src/components/checkbox/checkbox.md.vars.scss Outdated
Comment thread core/src/components/radio/test/basic/radio.e2e.ts
Comment thread core/src/components/radio/test/item/radio.e2e.ts
Comment thread core/src/components/radio/radio.tsx Outdated
ShaneK added 4 commits July 29, 2026 09:37
# Conflicts:
#	core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Chrome-linux.png
#	core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Chrome-linux.png
#	core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-focus-ios-ltr-Mobile-Chrome-linux.png
#	core/src/components/toggle/test/basic/toggle.e2e.ts-snapshots/toggle-in-item-focus-ios-ltr-Mobile-Chrome-linux.png

@brandyscarney brandyscarney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Mostly some questions on the expected behavior.

@thetaPC thetaPC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting on your responses to Brandy to determine my decision.

@thetaPC thetaPC left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ShaneK
ShaneK added this pull request to the merge queue Jul 31, 2026
Merged via the queue into main with commit 2f9c0b7 Jul 31, 2026
51 checks passed
@ShaneK
ShaneK deleted the FW-7585-FW-7586 branch July 31, 2026 22:09
ShaneK added a commit that referenced this pull request Aug 5, 2026
…ents

The keyboard focus indicator is drawn 7px outside the control, so it
widened the hit area and swallowed clicks aimed just past the control.
A checkbox clicked below itself kept focus instead of blurring, so the
next click emitted no ionFocus.

This only surfaced on next: main starts the focus-visible utility in
ion-app, so a setContent test without one never got ion-focused and
never drew the ring. next initializes it globally (#31165), so the ring
main added in #31295 now renders in those tests too.

The indicator is decorative and must never take pointer events. The ios
toggle uses box-shadow, which cannot capture them, so it needs no change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: core @ionic/core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants