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

Directly handle shift-stepping in RangeControl #34719

Closed
wants to merge 5 commits into from

Conversation

stokesman
Copy link
Contributor

@stokesman stokesman commented Sep 9, 2021

To fix: #34363

The linked issue is prevented by using our own logic to shift-step the input instead of the current approach which modifies the DOM step attribute and relies on the UA stepping behavior. The step attribute is a factor in validation so modifying it while a value is already present is likely to invalidate the value. An invalid value may get rounded to the nearest valid value by the UA. One (and maybe only) such UA is Firefox and that is why our current approach is problematic.

How has this been tested?

Manually, verifying that the linked issue can no longer be reproduced and that shift-stepping of range controls still works.

Screenshots

Shift+tab no longer causing the columns value to jump back to 1.

Also shows shift-step working toward the end of the video

after-range-control-shift-tab-reset.mp4

Shift-step in RTL

Aside: we seem to have style issues with RTL and RangeControl
after-RTL-range-control-shift-tab-reset

Types of changes

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).

@stokesman stokesman added the [Package] Components /packages/components label Sep 9, 2021
@github-actions
Copy link

github-actions bot commented Sep 9, 2021

Size Change: +126 B (0%)

Total Size: 1.06 MB

Filename Size Change
build/components/index.min.js 210 kB +126 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.19 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 134 kB
build/block-editor/style-rtl.css 13.9 kB
build/block-editor/style.css 13.8 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.23 kB
build/block-library/blocks/cover/style.css 1.23 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 983 B
build/block-library/blocks/gallery/editor.css 988 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 728 B
build/block-library/blocks/image/editor.css 728 B
build/block-library/blocks/image/style-rtl.css 482 B
build/block-library/blocks/image/style.css 487 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 488 B
build/block-library/blocks/media-text/style.css 485 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.5 kB
build/block-library/blocks/navigation/style.css 1.49 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 202 B
build/block-library/blocks/page-list/style.css 202 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-content/editor-rtl.css 138 B
build/block-library/blocks/post-content/editor.css 138 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 398 B
build/block-library/blocks/post-featured-image/editor.css 398 B
build/block-library/blocks/post-featured-image/style-rtl.css 143 B
build/block-library/blocks/post-featured-image/style.css 143 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 378 B
build/block-library/blocks/post-template/style.css 379 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 462 B
build/block-library/blocks/site-logo/editor.css 464 B
build/block-library/blocks/site-logo/style-rtl.css 153 B
build/block-library/blocks/site-logo/style.css 153 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.76 kB
build/block-library/editor.css 9.75 kB
build/block-library/index.min.js 147 kB
build/block-library/reset-rtl.css 527 B
build/block-library/reset.css 527 B
build/block-library/style-rtl.css 10.3 kB
build/block-library/style.css 10.3 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 47 kB
build/components/style-rtl.css 15.9 kB
build/components/style.css 15.9 kB
build/compose/index.min.js 10.3 kB
build/core-data/index.min.js 12.3 kB
build/customize-widgets/index.min.js 11.1 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 kB
build/edit-navigation/style-rtl.css 3.69 kB
build/edit-navigation/style.css 3.69 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 28.9 kB
build/edit-post/style-rtl.css 7.18 kB
build/edit-post/style.css 7.17 kB
build/edit-site/index.min.js 27.4 kB
build/edit-site/style-rtl.css 5.21 kB
build/edit-site/style.css 5.21 kB
build/edit-widgets/index.min.js 16.1 kB
build/edit-widgets/style-rtl.css 4.09 kB
build/edit-widgets/style.css 4.09 kB
build/editor/index.min.js 37.7 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.34 kB
build/format-library/style-rtl.css 668 B
build/format-library/style.css 670 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.88 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.28 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.42 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.27 kB
build/widgets/style-rtl.css 1.17 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@stokesman stokesman requested a review from ciampo September 9, 2021 23:24
@stokesman stokesman marked this pull request as ready for review September 10, 2021 02:42
@stokesman stokesman force-pushed the fix/range-control-shift-tab-reset branch 2 times, most recently from 327d73e to ac6500b Compare September 13, 2021 15:45
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.

Thank you for working on this, @stokesman !

In general, I'm always very cautious about moving away from native browser validation/behaviour, but I do understand that this may be required — and I appreciate that we are preventDefault-ing the keyDown event only when shift-stepping.

I tested the component in Storybook, and the issue explained in #34363 seems to have been addressed.

Production: After 95, shift+increment doesn't update the value to 100

range-control-shift-increment-prod.mp4

This PR: The value always gets updated to 100 when shift-incrementing

range-control-shift-increment-pr.mp4

Finally, I think we should add a few unit tests around the stepping and shift-stepping behaviour of the component. It would be best to add them in a separate PR, so that we can first write tests tailored to what we currently have in production. We can then leverage those tests in this and future PRs (like #34542) to get more confidence about the changes that are being introduced.

Aside: we seem to have style issues with RTL and RangeControl

Do you mind opening a separate issue to track this (and link back here)?

packages/components/src/range-control/input-range.js Outdated Show resolved Hide resolved
const { min, max, step } = props;
const modifiedStep = shiftStep * step;
const nextValue = operationList[ keyCode ]( value, modifiedStep );
onShiftStep( roundClamp( nextValue, min, max, modifiedStep ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the clamping here necessary?

If onShiftStep is assigned to the handleOnChange function, the clamping should already happen in there when calling setValue (which comes from the useControlledRangeValue hook).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good eye! roundClamp was added only for its rounding. If it's preferred I could look at changing this to round from lodash or maybe inlining the expression we need. Or perhaps this makes a case for having the useControlledRangeValue hook made step-aware so it could handle the rounding. Though that might be better explored as part of a PR for #34817.

ref={ ref }
step={ jumpStep }
Copy link
Contributor

Choose a reason for hiding this comment

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

Just noting that the step prop is now being passed directly when spreading { ...props }

@ciampo ciampo requested a review from diegohaz September 15, 2021 09:42
@ciampo ciampo added [Feature] UI Components Impacts or related to the UI component system [Type] Bug An existing feature does not function as intended labels Sep 15, 2021
@diegohaz
Copy link
Member

I agree that we shouldn't mutate the step attribute like that.

I tested the component on Storybook and noticed just one issue: if the first user interaction that changes the value of the range control uses Shift, it'll be updated as the initial value was 0, not 50. As a result, Shift+ArrowLeft will move the thumb to 0 (instead of 40), and Shift+ArrowRight will move it to 10 (instead of 60).

Another thing that I think is worth considering as an alternative solution: do we really need this shift interaction on the range control? I couldn't find any standards or conventions regarding this. If this may cause more problems in the future, I'd say we should consider removing this non-standard feature from the component (I'm not sure if this would be considered a breaking change, but I can't think of a code or even user interface that would break because the range control stopped doing something when isShiftStepEnabled or shiftStep were passed).

The native range control already provides a standard way to move with a larger step, which is by using PageUp and PageDown (or fn+ArrowUp and fn+ArrowDown). This works slightly different from what we currently have with the shift step: it always increments the current value by 10 instead of updating it to the nearest multiple of 10. So, pressing PageUp when the current value is 6 will change it to 16. Maybe we can just stick with the native behavior?

@stokesman
Copy link
Contributor Author

Thanks for testing and for your feedback @diegohaz. Great catch of that issue. I've pushed a commit to fix it. In the process, I realized the number input next to the range doesn't share that behavior. If the value is empty and you shift-step there it starts from 0. If that's an issue, it's an existing one. I'll await feedback before worrying about it.

The native range control already provides a standard way to move with a larger step … it always increments the current value by 10

That's good to know. I was unaware of the feature. Trying it out in Brave/Chromium, I happened to notice that, it steps by a tenth of the range, i.e. always by 10 percent. That is handy, thought it also seems nice that shiftStep provides configurability.


@ciampo, thanks for reviewing. I added an issue for the RTL style. Also (assuming we don't end up going with the alternative of dropping the feature), it makes sense to add the unit tests for (shift)stepping as well. The issue just caught by @diegohaz is a good example.

@ciampo
Copy link
Contributor

ciampo commented Sep 16, 2021

Thank you @stokesman for addressing the feedback (and opening a separate issue for the RTL issue)!

I tend to agree with the points made by @diegohaz — probably the better solution here is to remove the custom "shift-stepping" functionality completely, and rely more on what's natively supported by the browser. Not only this will offer a more standard experience to the users, but it will also simplify our code and make it easier to maintain.

I also don't think this would be considered as a breaking change. We could therefore remove the shift-stepping logic from the component, and mark the isShiftStepEnabled and shiftStep props as deprecated (and remove them from the README docs).

@stokesman
Copy link
Contributor Author

While I'd agree it's should be a safe (though technically breaking) change, I'm not favoring the removal. Also, I don't think it's quite right to say it "will offer a more standard experience to the users" as it makes it sound like the feature is altering part of the standard experience when it does not.

Still, I'd be glad to move forward with either decision. It would console me to see more opinions on it is all.

Remove the shift-stepping logic from the component, and mark the isShiftStepEnabled and shiftStep props as deprecated (and remove them from the README docs).

Should we consider leaving them in to allow configuration of the composed NumberControl? If not, do we leave them to their defaults or set isShiftStepEnabled to false?

@ciampo ciampo requested a review from gziolo September 16, 2021 16:11
@ciampo
Copy link
Contributor

ciampo commented Sep 16, 2021

I don't think it's quite right to say it "will offer a more standard experience to the users"

Your point here makes sense, I expressed myself poorly. What I was trying to say here is that, by removing the custom shift-stepping logic, the only type of interaction that the users would be able to have to increase/decrease the RangeControl would be the standard one offered by the browser.

Still, I'd be glad to move forward with either decision. It would console me to see more opinions on it is all.

Hey @gziolo (sorry for the ping!), do you have any opinions on potentially dropping the custom shift-stepping logic in the RangeControl component?

Should we consider leaving them in to allow configuration of the composed NumberControl? If not, do we leave them to their defaults or set isShiftStepEnabled to false?

This is an example of how we've "soft-deprecated" some props in the past — RangeControl would still be accepting those props (and passing them to the composed items).

Depending on what decision will be taken in this PR, I'd argue that we should then apply a similar decision to NumberControl to preserve the consistency between the two components.

@gziolo
Copy link
Member

gziolo commented Sep 17, 2021

Still, I'd be glad to move forward with either decision. It would console me to see more opinions on it is all.
Hey @gziolo (sorry for the ping!), do you have any opinions on potentially dropping the custom shift-stepping logic in the RangeControl component?

I wasn't even aware that this behavior is supported in RangeControl. It isn't something that is essential for the component to be fully functional, so if you were to remove it then nothing will break. I think it's more the question of what would be the best for the user. From my perspective, a harmful breaking change that we want to avoid is when value or onChange props would get removed or renamed 😄

@ciampo
Copy link
Contributor

ciampo commented Sep 17, 2021

I'm not favoring the removal.

@stokesman , what are the reasons behind your opposition to the removal?

if you were to remove it then nothing will break. I think it's more the question of what would be the best for the user. From my perspective, a harmful breaking change that we want to avoid is when value or onChange props would get removed or renamed 😄

Thank you Greg for chiming in! Personally, I agree with what you said regarding the removal of this functionality not being a breaking change for the users (although it technically is, as mentioned above). As mentioned before, I also find the points made by @diegohaz quite relevant — this interaction is not standard, and if we keep supporting it may cause more bugs in the future.

Depending on what decision will be taken in this PR, I'd argue that we should then apply a similar decision to NumberControl to preserve the consistency between the two components.

Do you have any option about the shift-stepping behaviour in NumberControl, @diegohaz? If we were to remove this functionality from RangeControl, I'd argue that we do the same in NumberControl too

@stokesman
Copy link
Contributor Author

stokesman commented Sep 17, 2021

what are the reasons behind your opposition to the removal?

I like and use the feature in NumberControl and UnitControl and I like the consistency in RangeControl though I'm not sure I've really used it.

I'd argue that we do the same in NumberControl too

Number inputs don't seem to have a UA provided alternative for larger steps like range inputs do. So while at least that component is still experimental, I'd rather RangeControl lack feature parity than also remove it from NumberControl and UnitControl (and despite being experimental they are in wide use in Gutenberg so user expectations may well exist) I'll concede that I imagine it's a small percent of users that know about or use the feature but it may be appreciated by future users as it seems a common feature in other design apps.

EDIT: accidentally submitted before finishing. Removed the part I'd not finished or had even decided to include.

@stokesman
Copy link
Contributor Author

I'd also like to say I am all for removing code and improving maintainability. I believe there are larger gains that can be made with regards to that without even removing features. I feel like we are eyeing this due to happenstance and it's not really going to be a burden.

Copy link
Contributor

@andrewserong andrewserong left a comment

Choose a reason for hiding this comment

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

Nice work here @stokesman, and thanks for digging deep into the issue! I see some of the comments sought to get some more opinions, so I thought I'd jump in and test out the PR and add a couple of thoughts.

I think the way this is implemented currently introduces a regression. In the useJumpStep hook, it's a fairly naive approach and updates the step value when the shift key is held. This means that it applies to click+drag (in additional to the direction keys) which was highlighted in the PR that introduced the feature.

Production: shift-clicking allows the jump step to be used for the RangeControl

In Storybook, shift-clicking and dragging shifts the value by increments of 10 in production. (In the screengrab, the shift key is released for a moment to show that it toggles while dragging)

Kapture 2021-09-21 at 12 07 16

Current behaviour

In Storybook, shift-clicking and dragging doesn't affect the step.

Kapture 2021-09-21 at 12 08 56

Without the shift-click-drag feature, I think I'm leaning toward the feedback some of the others have given, that it might be worth removing the feature from the range control instead of adding additional complexity to the component. In the naive approach that the useJumpStep hook uses, it doesn't need to worry about any other key than the shift key, and it also doesn't need to account for RTL.

While it's often good to hone in on the exact behaviour we'd like to control, I think unless we have a concrete example of users taking advantage of the interaction and depending on it for common tasks, I'd lean toward seeing if we can remove the additional complexity, and fall back to browser behaviour where we can. Though, I agree, this would mean that there'd be a bit of a mismatch between RangeControl and NumberControl.

To take an iterative approach, would it be worth exploring removing the shift step behaviour from the InputRange (but retain it for the range control's NumberControl), so that we can fix #34363 in the short-term, and then look at adding back in the shift step behaviour in a separate PR if it's still needed? It'd also be good to see if we can continue to contain the logic in a hook rather than directly on the component, but I'm aware this might be challenging to get working properly with the step logic.

I'm not sure how much that helps, but I'm happy to help out with further testing!

@aaronrobertshaw
Copy link
Contributor

You have my thanks as well @stokesman for your efforts on this, nice work! 👍

I initially found my way here via your other work on the NumberControl and given the nudges for extra opinions, figured I could add my two cents even if it only echos some of the existing sentiments discussed earlier.

Firstly, while testing this I also came across the issue @andrewserong highlighted. That being, holding down shift while dragging the slider is no longer supported. If we are to retain the shift-stepping behaviour, I'd expect that we'd maintain current functionality as well.

Some of my thoughts around the discussion so far include:

  • Reducing complexity is good and generally pays off in the long term
  • Bringing our component in line with standard browser behaviour sounds like a win
    • Even if the reduction in maintenance or future issues is minimal
  • Improving the consistency between the components on the web vs native would be a positive, if possible
  • Shift stepping for the NumberControl appears a much more common use
  • Personally, I've never used the shift stepping on the range control until testing this
  • I'm not sure we have to be too rigid in terms of consistency between RangeControl and the NumberControl

My vote would be to explore dropping the shift stepping support from the RangeControl while keeping it for the NumberControl. Drawing the line there between NumberControl and RangeControl makes sense to me and appears justified over forcing consistency given the increased use of the feature for NumberControl.

I agree also with the sentiment that this does not have to be the end of the process. We can revisit the feature when or if it is proven desired.

Hope that helps a little.

@ciampo
Copy link
Contributor

ciampo commented Sep 21, 2021

Thank you @andrewserong and @aaronrobertshaw for taking a look at this PR and sharing your perspective.

After reading everyone's feedback, the most reasonable approach to me is to remove the shift-stepping behaviour from RangeControl as a first step, in order to fix #34363.

We can then open a new issue to:

  • discuss if we should re-add the shift-stepping behaviour to RangeControl. In case we do, we'd need to discuss the best approach that doesn't introduce regression (and probably add tests to the component too).
  • in case we decided not to re-add this behaviour to RangeControl, discuss if it should be removed from NumberControl too

@stokesman stokesman force-pushed the fix/range-control-shift-tab-reset branch from 903241c to 0b8034e Compare September 21, 2021 20:22
@stokesman
Copy link
Contributor Author

stokesman commented Sep 21, 2021

I appreciate the well considered comments left by @andrewserong and @aaronrobertshaw. Thank you both and again for testing this out.

More for a little challenge than anything else, I've made and pushed a change to knock out that regression. The whole approach was reworked and it some ways (lack of needing to think about RTL) it is less complex but roughly the same I think.

I'm not strongly opposed to removing the feature and my main thing was it seems like we lacked a strong reason to do so. I'll agree, in this circumstance, we don't need a strong reason because we are confident this can't break anything besides user expectation (and we believe that to be practically nil).

Anyway, now we have #35020 which I believe does what folks are encouraging here.

@stokesman stokesman closed this Sep 22, 2021
@stokesman stokesman deleted the fix/range-control-shift-tab-reset branch September 23, 2021 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] UI Components Impacts or related to the UI component system [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.

Columns slider: Number of columns reset to 1 when using Tab+Shift
6 participants