ToggleGroupControl: Don't set value on focus after a reset#66151
ToggleGroupControl: Don't set value on focus after a reset#66151
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
| toggleGroupControlContext.value === null || | ||
| toggleGroupControlContext.value === ''; |
There was a problem hiding this comment.
Due to how we add a layer of value conversion in controlled mode, the Ariakit store will hold a null value on first render with no value provided, but then an empty string after a consumer resets the value to undefined.
| // Ensures that the active id is also reset after the value is "reset" by the consumer. | ||
| useEffect( () => { | ||
| if ( selectedValue === '' ) { | ||
| radio.setActiveId( undefined ); | ||
| } | ||
| }, [ radio, selectedValue ] ); |
There was a problem hiding this comment.
I can feel the tech debt catching up to us 😅
There was a problem hiding this comment.
Food for thought: I wonder if this can be improved with a centralized controlled component layer that all controlled components would use. Probably a too idealistic idea, since some components use Ariakit and others do not, and this layer would be quite complicated to cover all cases.
There was a problem hiding this comment.
I think that the most practical fix here is to change the APIs to follow the standard convention for controlled / uncontrolled component. Since that would be a breaking change, we could just release a V2 of the component that would give us also a chance to:
- implement / test the new design spec alongside the legacy one
- review the current API strategy around "deselectability" and potentially multiple selection (should they be separate components? Or different subcomponents?)
There was a problem hiding this comment.
For this case specifically, I think there might be room to argue that resetting the active id on empty-ish (or invalid) values should be handled by Ariakit out of the box. I'll try and follow up.
|
Flaky tests detected in 1c8b689. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11356382384
|
| <Ariakit.Radio | ||
| disabled={ disabled } | ||
| onFocusVisible={ () => { | ||
| const selectedValueIsNullish = |
There was a problem hiding this comment.
Naming nit: nullish often refers to null or undefined, so if someone isn't reading closely, they might be confused and expect this checks for undefined and not an empty string.
There was a problem hiding this comment.
Maybe selectedValueIsEmpty ? Or even inlining the check?
There was a problem hiding this comment.
Good point, I'll go with selectedValueIsEmpty here. (It started as an inline condition, but it was hard to parse/understand so I prefer it named.)
| // Ensures that the active id is also reset after the value is "reset" by the consumer. | ||
| useEffect( () => { | ||
| if ( selectedValue === '' ) { | ||
| radio.setActiveId( undefined ); | ||
| } | ||
| }, [ radio, selectedValue ] ); |
There was a problem hiding this comment.
Food for thought: I wonder if this can be improved with a centralized controlled component layer that all controlled components would use. Probably a too idealistic idea, since some components use Ariakit and others do not, and this layer would be quite complicated to cover all cases.
| expect( radio ).not.toBeChecked(); | ||
| } ); | ||
|
|
||
| if ( mode === 'controlled' ) { |
There was a problem hiding this comment.
Should we move it next to the other controlled-only tests?
There was a problem hiding this comment.
No strong opinion, but I think I prefer it here because it's closely related to the test right above it.
|
There was a conflict while trying to cherry-pick the commit to the wp/6.7 branch. Please resolve the conflict manually and create a PR to the wp/6.7 branch. PRs to wp/6.7 are similar to PRs to trunk, but you should base your PR on the wp/6.7 branch instead of trunk. |
|
@mirka just a ping in case you didn't notice the failed backport |
* Add test * ToggleGroupControl: Don't set value on focus after a reset * Add changelog * Rename to `selectedValueIsEmpty` Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org> # Conflicts: # packages/components/CHANGELOG.md
|
Backported at 4a7de72 |
…#66151) * Add test * ToggleGroupControl: Don't set value on focus after a reset * Add changelog * Rename to `selectedValueIsEmpty` Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla <tyxla@git.wordpress.org> Co-authored-by: ciampo <mciampini@git.wordpress.org>
Bug discovered in #65386 (comment)
What?
Fixes an incomplete bug fix in #65892 where ToggleGroupControl could still autoselect an option on focus after the selected value was reset by the consumer.
Testing Instructions for Keyboard
Modify the Storybook story so it has a reset button, like this: