Description
Provide a general summary of the issue here
Sequential presses to a Radio or Checkbox component will call onBlur upon the second press.
🤔 Expected Behavior?
onBlur shouldn't be called on sequential presses of the "input" element (red border)
😯 Current Behavior
If a checkbox or radio is already focused, pressing on the element a second time will call onBlur (since it is technically the label getting pressed, not the actual input).
💁 Possible Solution
Other input elements (eg. TextField) leave the rendering of the Label and Input elements up to the consumer.
🔦 Context
This is technically expected based on default HTML behaviour and the structure of the components, but unexpected for a user (since it looks like they are pressing on the input).
As a side effect, my validation for these components is running unexpectedly when hooked into a form.
🖥️ Steps to Reproduce
https://codesandbox.io/p/sandbox/exciting-nightingale-wjx2jz
Version
react-aria-components@1.7.1
What browsers are you seeing the problem on?
Microsoft Edge, Safari, Chrome, Firefox
If other, please specify.
No response
What operating system are you using?
MacOS
🧢 Your Company/Team
No response
🕷 Tracking Issue
No response
Activity
snowystinger commentedon Apr 8, 2025
We could probably change it to call onBlur/onFocus for focusin/focusout on the label instead. I think that'd be the behaviour you're expecting. Right now it's just using
useFocusable
for themreact-spectrum/packages/@react-aria/radio/src/useRadio.ts
Line 79 in ad4681f
This would be an override for RAC, though, since the hook doesn't know that the label will wrap the input.
uniqueeest commentedon Apr 8, 2025
@snowystinger hi. i want to resolve this issue.
uniqueeest commentedon Apr 15, 2025
@snowystinger Is it correct that you want me to move the onFocus, onBlur event to the label? The same issue occurs even if you proceed in that way. I'd appreciate a little help with this situation.
nwidynski commentedon Apr 15, 2025
@uniqueeest Something like this should do the trick:
uniqueeest commentedon Apr 16, 2025
@nwidynski I don't think that's a good idea, because we have two different types of focus, blur, so we have a type conflict.
nwidynski commentedon Apr 16, 2025
@uniqueeest You can safely ignore the type errors or recast the FocusableElement. A type mismatch was expected as this is an override, as @snowystinger mentioned.
Just make sure to also adjust the type signature of the component.
uniqueeest commentedon Apr 16, 2025
@nwidynski
If you do this, there won't be an onblur event😂
benwilliams140 commentedon Apr 16, 2025
What about something like this? facebook/react#6410 (comment)
Note the "focusenter" and "focusleave" logs (these are the checks you'd want)
nwidynski commentedon Apr 16, 2025
@uniqueeest I'm sorry, I read this issue wrong. What you actually want to do is:
This will change the target of focus events to be the
label
instead of the hiddeninput
. You can further differentiate between the event types by applying the example @benwilliams140 mentioned.uniqueeest commentedon Apr 17, 2025
@nwidynski That way, the onBlur event is called right away from the approach...
As soon as I click on the label, the focus goes straight into the input and the label seems to be onblur.
benwilliams140 commentedon Apr 17, 2025
@uniqueeest yes that's default browser behaviour (to focus the input after clicking on the label). You would need to differentiate between the event types to ignore blur events where focus is still within the label