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

Support "any" step in NumberControl and RangeControl #34542

Merged
merged 14 commits into from
Oct 11, 2021

Conversation

stokesman
Copy link
Contributor

@stokesman stokesman commented Sep 3, 2021

Closes #34816

Currently, NumberControl allows step="any" but attempting to use the arrow keys or dragging to change the value results in NaN. This PR fixes that.

Support in RangeControl presents a bit of a design challenge #34542 (comment) and alternate ideas on resolving it are welcome.

How has this been tested?

Unit tests and manually comparing behavior of NumberControl with behavior of an input[type="number] element using the same step values.

Screenshots

NumberControl support of "any" step with arrow keys and dragging

number-control-any-step-and-shift-rounding

RangeControl switching between step of 1 and "any"

range-control-step-1-or-any.mp4

RangeControl marks with "any" step

The mark handling code needed a tiny revision to treat step="any" as if the step was 1. While testing that I noticed that the styling for marks has regressed but it's a separate issue (#35153).

range-control-step-any-with-marks.mp4

Types of changes

enhancement

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).

@github-actions
Copy link

github-actions bot commented Sep 3, 2021

Size Change: -10 B (0%)

Total Size: 1.07 MB

Filename Size Change
build/components/index.min.js 217 kB -10 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/api-fetch/index.min.js 2.21 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.2 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/index.min.js 135 kB
build/block-editor/style-rtl.css 13.9 kB
build/block-editor/style.css 13.9 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 474 B
build/block-library/blocks/button/editor.css 474 B
build/block-library/blocks/button/style-rtl.css 600 B
build/block-library/blocks/button/style.css 600 B
build/block-library/blocks/buttons/editor-rtl.css 315 B
build/block-library/blocks/buttons/editor.css 315 B
build/block-library/blocks/buttons/style-rtl.css 370 B
build/block-library/blocks/buttons/style.css 370 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 206 B
build/block-library/blocks/columns/editor.css 205 B
build/block-library/blocks/columns/style-rtl.css 497 B
build/block-library/blocks/columns/style.css 496 B
build/block-library/blocks/cover/editor-rtl.css 666 B
build/block-library/blocks/cover/editor.css 670 B
build/block-library/blocks/cover/style-rtl.css 1.17 kB
build/block-library/blocks/cover/style.css 1.17 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 977 B
build/block-library/blocks/gallery/editor.css 982 B
build/block-library/blocks/gallery/style-rtl.css 1.6 kB
build/block-library/blocks/gallery/style.css 1.59 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 731 B
build/block-library/blocks/image/editor.css 730 B
build/block-library/blocks/image/style-rtl.css 491 B
build/block-library/blocks/image/style.css 494 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 493 B
build/block-library/blocks/media-text/style.css 490 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 568 B
build/block-library/blocks/navigation-link/editor.css 570 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 300 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/style-rtl.css 195 B
build/block-library/blocks/navigation-submenu/style.css 195 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/editor-rtl.css 1.72 kB
build/block-library/blocks/navigation/editor.css 1.72 kB
build/block-library/blocks/navigation/style-rtl.css 1.62 kB
build/block-library/blocks/navigation/style.css 1.61 kB
build/block-library/blocks/navigation/view.min.js 2.74 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 198 B
build/block-library/blocks/page-list/style.css 198 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 273 B
build/block-library/blocks/paragraph/style.css 273 B
build/block-library/blocks/post-author/editor-rtl.css 210 B
build/block-library/blocks/post-author/editor.css 210 B
build/block-library/blocks/post-author/style-rtl.css 182 B
build/block-library/blocks/post-author/style.css 181 B
build/block-library/blocks/post-comments-form/style-rtl.css 140 B
build/block-library/blocks/post-comments-form/style.css 140 B
build/block-library/blocks/post-comments/style-rtl.css 360 B
build/block-library/blocks/post-comments/style.css 359 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 396 B
build/block-library/blocks/post-featured-image/editor.css 397 B
build/block-library/blocks/post-featured-image/style-rtl.css 146 B
build/block-library/blocks/post-featured-image/style.css 146 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 391 B
build/block-library/blocks/post-template/style.css 392 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 378 B
build/block-library/blocks/pullquote/style.css 378 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 262 B
build/block-library/blocks/query-pagination/editor.css 255 B
build/block-library/blocks/query-pagination/style-rtl.css 234 B
build/block-library/blocks/query-pagination/style.css 231 B
build/block-library/blocks/query-title/editor-rtl.css 85 B
build/block-library/blocks/query-title/editor.css 85 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 220 B
build/block-library/blocks/quote/theme.css 222 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 374 B
build/block-library/blocks/search/style.css 375 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 769 B
build/block-library/blocks/site-logo/editor.css 769 B
build/block-library/blocks/site-logo/style-rtl.css 165 B
build/block-library/blocks/site-logo/style.css 165 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 165 B
build/block-library/blocks/social-link/editor.css 165 B
build/block-library/blocks/social-links/editor-rtl.css 812 B
build/block-library/blocks/social-links/editor.css 811 B
build/block-library/blocks/social-links/style-rtl.css 1.3 kB
build/block-library/blocks/social-links/style.css 1.3 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 636 B
build/block-library/blocks/template-part/editor.css 635 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/term-description/editor-rtl.css 90 B
build/block-library/blocks/term-description/editor.css 90 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/common-rtl.css 853 B
build/block-library/common.css 849 B
build/block-library/editor-rtl.css 9.89 kB
build/block-library/editor.css 9.89 kB
build/block-library/index.min.js 148 kB
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-library/style-rtl.css 10.3 kB
build/block-library/style.css 10.4 kB
build/block-library/theme-rtl.css 665 B
build/block-library/theme.css 669 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/blocks/index.min.js 45.7 kB
build/components/style-rtl.css 15.3 kB
build/components/style.css 15.3 kB
build/compose/index.min.js 10.3 kB
build/core-data/index.min.js 12.4 kB
build/customize-widgets/index.min.js 11.2 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.45 kB
build/edit-navigation/index.min.js 15.3 kB
build/edit-navigation/style-rtl.css 3.74 kB
build/edit-navigation/style.css 3.74 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 29.2 kB
build/edit-post/style-rtl.css 7.2 kB
build/edit-post/style.css 7.19 kB
build/edit-site/index.min.js 29.4 kB
build/edit-site/style-rtl.css 5.5 kB
build/edit-site/style.css 5.5 kB
build/edit-widgets/index.min.js 15.7 kB
build/edit-widgets/style-rtl.css 4.1 kB
build/edit-widgets/style.css 4.1 kB
build/editor/index.min.js 37.5 kB
build/editor/style-rtl.css 3.76 kB
build/editor/style.css 3.75 kB
build/element/index.min.js 3.17 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 5.93 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.72 kB
build/keycodes/index.min.js 1.3 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.19 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.6 kB
build/server-side-render/index.min.js 1.52 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.74 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@ciampo ciampo added [Feature] Component System WordPress component system [Feature] UI Components Impacts or related to the UI component system [Type] Bug An existing feature does not function as intended labels Sep 7, 2021
modifier
);
if ( delta !== 0 ) {
delta = Math.ceil( Math.abs( delta ) ) * Math.sign( delta );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The value of delta comes from react-use-gesture and is a decimal value. It's converted to an integer in order to preserve the NumberControl's decimal value as entered (when step="any"). Done via Math.ceil etc. because single pixel movements produce values like:
image

@ciampo
Copy link
Contributor

ciampo commented Sep 7, 2021

Hey @stokesman , thank you for your PR!

Currently, NumberControl allows step="any"

Would you be able to point me to where this is stated? In the README, the step prop is listed as of type Number, and therefore it doesn't support any as a value.

Along with that, it revises the rounding used while holding the Shift key

While I understand that this may be a more predictable behaviour for you, I'll have to look more into it and consider if this is a change that we'd want to make to the component. It may be confusing to users that got used to the current rounding logic and therefore be seen as a sort of breaking change.

(cc @gziolo @diegohaz )

@ciampo ciampo requested review from gziolo and diegohaz September 7, 2021 17:06
@ciampo ciampo removed the [Type] Bug An existing feature does not function as intended label Sep 7, 2021
@stokesman
Copy link
Contributor Author

stokesman commented Sep 7, 2021

Thanks for taking a look and for the feedback @ciampo.

In the README, step is listed as of type Number, and therefore it doesn't support any as a value.

I wrote "allows step="any"" because it seems incidental rather than intentional. However, it also seems like a useful thing to support. The README also states that "NumberControl is an enhanced HTML input[type="number] element". Was lack of support for step="any" intended as an enhancement then?

It may be confusing to users that got used to the current rounding logic and therefore be seen as a sort of breaking change.

I believe that most users of the feature only even know about it because they use the same feature in other applications. All other applications I know with the feature, do not round by an increased amount while holding Shift. So for those relatively advanced users, I think we'd avoid frustration with the unique implementation we currently have.

Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

@stokesman Thanks for working on this! 👍

The updated NumberControl works as advertised.

Personally, I like the consistent and predictable application of step values. That said, I can appreciate that this is a change away from the current behaviour that some users may not perceive as a bug and have grown accustomed to.

The docs for the shiftStep prop don't seem to communicate any rounding of the value based off of it. So perhaps that aspect of the changes in this PR are more in line with the advertised functionality?

Amount to increment by when the SHIFT key is held down. This shift value is a multiplier to the step value. For example, if the step value is 5, and shiftStep is 10, each jump would increment/decrement by 50.

Regarding the support of "any" I'll happily defer to @ciampo on that. 🙂

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

About supporting step="any"

The README also states that "NumberControl is an enhanced HTML input[type="number] element". Was lack of support for step="any" intended as an enhancement then?

Seen in this light, it does look like adding support for any as a valid value for the step prop would increase this component's adherence to the HTML input spec.

It would be good, then, to update the README:

  • the type of the step prop should become something like number | "any"
  • there should be a short paragraph explaining what to expect when setting step="any"

It'd be also good to add support for any to the Storybook example

About the shift step rounding changes

@aaronrobertshaw made a very good point:

The docs for the shiftStep prop don't seem to communicate any rounding of the value based off of it. So perhaps that aspect of the changes in this PR are more in line with the advertised functionality?

So I'd say that we can go ahead and implement this change — but the approach I would take would be slightly different: I would instead look at changing the logic directly in the useJumpStep function.

Splitting across two separate PRs

Since the step="any" attribute is also supported by <input type="range" />, similar changes to the ones applied to NumberControl in this PR should be also applied to RangeControl.

Also, since useJumpStep is also used by RangeControl, I would propose that:

  • We keep this PR focused on adding support of the step="any" prop to both NumberControl and RangeControl
  • We make changes to the shift step rounding logic in a separate PR, by changing the useJumpStep function

@ciampo ciampo added the [Type] Enhancement A suggestion for improvement. label Sep 8, 2021
@stokesman stokesman force-pushed the fix/number-control-any-step-and-shift-rounding branch from e24fa9a to 62e73d0 Compare September 10, 2021 01:31
@stokesman
Copy link
Contributor Author

Thank you both @aaronrobertshaw and @ciampo 🙇

  • We keep this PR focused on adding support of the step="any" prop to both NumberControl and RangeControl

I like that idea and have pushed some changes in that direction. I've yet to add any changes for RangeControl and I'll draft this again for now.

  • We make changes to the shift step rounding logic in a separate PR, by changing the useJumpStep function

I'm all for the separate PR and sharing any appropriate abstractions but, if we change useJumpStep, I have a feeling it will be a nigh 100% rewrite. We can get into the details as progress warrants. In related news, I've just opened a PR that incidentally removes the hook from RangeControl as a solution to this recent issue

@stokesman stokesman marked this pull request as draft September 10, 2021 02:49
@stokesman stokesman changed the title Support "any" step in NumberControl and revise shift step rounding [WIP] Support "any" step in NumberControl and RangeControl Sep 10, 2021
@stokesman
Copy link
Contributor Author

stokesman commented Sep 28, 2021

Thanks for the testing and feedback Marco! I've gone ahead with most of the suggestions you made.

In brief, I think that the round-clamping logic is not behaving as expected when using a mix of normal stepping and shift-stepping. Also, the same behaviour can be replicated with an integer as the shift step.

Unless it was partly due to the mistake I'd made (and you caught #34542 (comment)) then I believe all that is existing and what this PR is helping us get closer to fixing. I have #34566 waiting in the wings that adds some tests and fixes for roundClamp. It was depending slightly on something from the original version of this PR (that also included the shift-step refinement) so I'd drafted it until those get worked out.

…notice how the value, despite not being valid, doesn't get round-clamped to the closest valid value.

I think that is #33291 for which #34128 exists. (Also not sure if you expected the UA to do it. None that I know of do that for number inputs just range inputs (and that's only Firefox as far as I know)).

@stokesman
Copy link
Contributor Author

I just went through and tested on the github hosted storybook and could reproduce exactly the results described in #34542 (review). Those are expected in that they are what we currently ship. We do have some unit tests that should fail given any shift-step changes (they did in the original version of this PR which included shift-step rounding changes).

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

I just went through and tested on the github hosted storybook and could reproduce exactly the results described in #34542 (review). Those are expected in that they are what we currently ship

I can confirm that the behaviour that I flagged previously can be also replicated in production — so we shouldn't count it as a blocker for this PR.

We do have some unit tests that should fail given any shift-step changes (they did in the original version of this PR which included shift-step rounding changes).

That's a good point (although they were not testing for the bug that I flagged earlier).

In that regard, thank you for flagging #34566 and #34128 — it'd be great if we could work on it as a follow-up, I believe those fixes and the additional tests are much needed, and I would argue they should take precedence over resuming the work in #34817.


I was ready to approve this PR, but I decided to give it a final look — and that's when I discovered another unexpected behaviour, which I believe should be fixed in this PR since it's related to step="any".

Steps to reproduce:

  • I set step="any"
  • I set the value of the input to a non-integer number, e.4. 4.3
  • I increment/decrement the value via keyboard, works as expected
  • I press enter to force the rounding — the .3 part of the number is preserved, as expected
  • I click-drag, the number increments/decrements as expected
  • I click on the up/down arrows on the right side of the input — the value gets rounded to the closest integer. I think this behaviour is unexpected and should be updated to reflect the rest of the interactions listed above — what do you think?

Here's a screencast of the behaviour that I just described

Kapture.2021-10-01.at.12.56.54.mp4

Finally, I think it would be nice if we could add tests specific to steps="any" (as part of this PR).

@ciampo ciampo mentioned this pull request Oct 1, 2021
62 tasks
@stokesman stokesman force-pushed the fix/number-control-any-step-and-shift-rounding branch from 234ff0e to a041308 Compare October 5, 2021 13:00
@stokesman
Copy link
Contributor Author

stokesman commented Oct 5, 2021

Thanks for testing this once again @ciampo.

I click on the up/down arrows on the right side of the input — the value gets rounded to the closest integer. I think this behaviour is unexpected and should be updated to reflect the rest of the interactions listed above — what do you think?

I agree and it presents a bit of a dilemma. We can't (easily) have both shift-step working for clicks on those up/down arrows and have them behave as they should natively in regards to not rounding "any" steps. It's because the shift-step for those arrows happens the same way it did for RangeControl, by mutating the DOM step attribute and letting the browser handle it. To handle with our own logic is possible but not trivial.

I've pushed a change for what I think is the sensible way to proceed and that is removing the mutation of the step attribute. So clicking the arrows while holding shift won't shift-step. We could compromise and remove it only when step="any" but there doesn't seem to be much reason to bother. Given that the component is experimental and that it seems unlikely many folks expect to shift-step while clicking those arrows, I think it's fine to remove it. Additionally, mutating the attribute may not cause any known issues but it's a bit dirty as it can temporarily invalidate the input.

One more related note is it looks like we may be adding our own stepping arrows to NumberControl in which case having them shift-step would be relatively easy.
image

I've added some tests for step="any" with NumberControl to the PR. They are only for keyboard input because testing the drag or "spin" arrows in jsdom would be a fancy trick. I looked at adding some tests for RangeControl but can't see there's any worthwhile tests to make there.

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Given that the component is experimental and that it seems unlikely many folks expect to shift-step while clicking those arrows, I think it's fine to remove it. Additionally, mutating the attribute may not cause any known issues but it's a bit dirty as it can temporarily invalidate the input.

One more related note is it looks like we may be adding our own stepping arrows to NumberControl in which case having them shift-step would be relatively easy.

Thank you for the detailed explanation. I agree with the whole reasoning here.

I can also confirm that the issue that I flagged in my previous comment is now fixed.

I've added some tests for step="any" with NumberControl to the PR. They are only for keyboard input because testing the drag or "spin" arrows in jsdom would be a fancy trick. I looked at adding some tests for RangeControl but can't see there's any worthwhile tests to make there.

Thank you for this as well.

I am not 100% sure I like how we're hiding the number input in the RangeControl component when step="any", but it's probably something we can iterate on in a separate PR as a follow-up.

Let's merge this 🚀 (and thank you again for the patience while working on this PR)

@stokesman stokesman force-pushed the fix/number-control-any-step-and-shift-rounding branch from a041308 to f39dc37 Compare October 11, 2021 03:37
@stokesman
Copy link
Contributor Author

Thank you @ciampo 🙇 I just pushed one more commit for a changelog entry (on a rebase). A test may have flaked but as soon as I can get it all green, I'll merge it.

One other thing, It looks like useJumpStep will become dead code when this merges. I suppose it won't hurt to leave it be for now but thought it worth noting.

@stokesman stokesman merged commit f37f80f into trunk Oct 11, 2021
@stokesman stokesman deleted the fix/number-control-any-step-and-shift-rounding branch October 11, 2021 05:29
@github-actions github-actions bot added this to the Gutenberg 11.8 milestone Oct 11, 2021
@ciampo
Copy link
Contributor

ciampo commented Oct 11, 2021

One other thing, It looks like useJumpStep will become dead code when this merges. I suppose it won't hurt to leave it be for now but thought it worth noting.

Thank you for flagging it. Let's continue this conversation in #34817

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Component System WordPress component system [Feature] UI Components Impacts or related to the UI component system [Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Components: support step="any" in NumberControl and RangeControl
3 participants