Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RangeControl: disable reset button consistently #64579

Merged
merged 8 commits into from
Aug 19, 2024
Merged

Conversation

ciampo
Copy link
Contributor

@ciampo ciampo commented Aug 16, 2024

What?

Fixes #63061

Disable the reset button in RangeControl when the current value of the component is already equal to the "reset value".

Why?

Leaving the reset button enabled in this scenario can cause confusion in the end user and make the UX worse.

How?

By tweaking the disabled logic for the reset button, making sure that value is compared to the correct "reset" value in every scenario.

I also updated unit tests in the process.

Testing Instructions

In Storybook, set allowReset to true and play around the RangeControl component and the initialPosition and resetFallbackValue props. Make sure that:

  • if resetFallbackValue is provided, the value resets to resetFallbackValue;
  • otherwise, if initialPosition is provided, the value resets to initilaPosition;
  • otherwise, the slider resets to the value half way between min and max, and the number input clears up.

In any case, the reset button should become disabled when resetting the RangeControl component.

@ciampo ciampo self-assigned this Aug 16, 2024
Comment on lines 184 to 193
// Reset to `resetFallbackValue` if defined, otherwise set internal value
// to `null`.
const resetValue = Number.isNaN( resetFallbackValue )
? null
: resetFallbackValue ?? null;

if ( isNaN( resetValue ) ) {
resetValue = null;
onChangeResetValue = undefined;
}
// const resetValue = computeResetValue( {
// resetFallbackValue,
// initialPosition,
// } );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mirka pinging you for some early feedback.

I took a look at the component, specifically about how it behaves when clicking the reset button. This is what I gathered:

  • when resetFallbackValue is provided:
    • we call setValue(resetFallbackValue), but if the component is controlled, the external value still prevails;
    • onChange() is called with resetFallbackValue, which causes the parent component to update the value prop, which causes the internal value to update to resetFallbackValue;
  • when initialPosition is provided:
    • we call setValue(null), but if the component is controlled, the external value still prevails;
    • onChange() is called with undefined, which causes the parent component to update the value prop, which causes the internal value to update to fallback to initialPosition;
  • when neither resetFallbackValue nor initialPosition are provided:
    • we call setValue(null), but if the component is controlled, the external value still prevails;
    • onChange() is called with undefined, which causes the parent component to update the value prop, but since there is not initialPosition to fallback to, the internal value stays null;

I extracted the computeResetValue function which kind of codifies the expected reset value logic. But if I applied it to the handleOnReset function, it would cause some changes to how the component works (especially to the arguments of onChange).

My gut feeling is to keep this PR's scope more limited and focus on disabling the reset button correctly.

Separately, IMO we should consider re-thinking the controlled/uncontrolled logic entirely, so that onChange and the reset functionality behave in a more "standard" fashion (from a quick test, the reset button doesn't seem to work at all in uncontrolled mode). If we think that the changes are breaking enough, we may even want to consider an ariakit rewrite in the process (and consider the plan highlighted in #40507)

Copy link
Member

Choose a reason for hiding this comment

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

Great investigation, thank you. It's a good look into the kind of things we'll be dealing with for #57004.

My gut feeling is to keep this PR's scope more limited and focus on disabling the reset button correctly.

Definitely. And also, I just noticed that allowReset may be a candidate for deprecation. It doesn't look like it's used anywhere in the codebase anymore, as well as the one on BoxControl. Makes sense, because we've delegated all reset functionality to the ToolsPanel.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, i'll keep the scope of this PR limited to fixing the reset button disabled behavior.

I just noticed that allowReset may be a candidate for deprecation.

True, we could also open a follow-up PR to deprecated allowReset and resetFallbackValue, although it's probably not a high priority.

@ciampo ciampo changed the title Add some temporary test TODOs RangeControl: disable reset button consistently Aug 16, 2024
@ciampo ciampo force-pushed the fix/range-control-reset branch from 8721a64 to 1872e89 Compare August 17, 2024 20:08
@ciampo ciampo requested a review from a team August 17, 2024 20:19
@ciampo ciampo added [Type] Bug An existing feature does not function as intended [Package] Components /packages/components labels Aug 17, 2024
@ciampo ciampo marked this pull request as ready for review August 17, 2024 20:19
@ciampo ciampo requested a review from ajitbohra as a code owner August 17, 2024 20:19
Copy link

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ciampo <[email protected]>
Co-authored-by: mirka <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

The changes make sense, and tests well 👍

@ciampo ciampo enabled auto-merge (squash) August 19, 2024 07:30
@ciampo ciampo merged commit bca4aeb into trunk Aug 19, 2024
62 checks passed
@ciampo ciampo deleted the fix/range-control-reset branch August 19, 2024 07:39
@github-actions github-actions bot added this to the Gutenberg 19.1 milestone Aug 19, 2024
bph pushed a commit to bph/gutenberg that referenced this pull request Aug 31, 2024
* Add some temporary test TODOs

* Temporarily comment out initialPosition's default value in Storybook

* Tweak reset button disable logic, extract computeResetValue function

* Update test comments

* Clean up code

* Update reset-related tests

* Restore Storybook default args

* CHANGELOG

---

Co-authored-by: ciampo <[email protected]>
Co-authored-by: mirka <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RangeControl: Reset button isn't disabled when expected
2 participants