Todo for v2
stipsan opened this issue · comments
Moving it out of #155 so this can be done in multiple PRs.
Guiding principles behind the rebuild
- Ponyfill principles, never alter globals that one day could break the web (cough cough mootools cough cough)..
- Minimal in design and API surface.
- Follow the
Element.scrollIntoView(ScrollIntoViewOptions)
spec and related draft specs instead of reinventing the wheel. - Comprehensive testing suite to ensure the spec is implemented correctly, and that common use cases are accounted for.
- Modular design, favor composition over configuration.
- Adapts to your priorities. If speed and bundlesize is more important than every visitor seeing a nice smooth scroll then the default version is enough. If a consistent user experience for all your users is more important, opt in to the smooth-behavior ponyfill.
- Sensible defaults, zero-config (as long it doesn't break spec compliance).
- Lifecycle hooks instead of a million options.
Entirely new API, implementing Element.scrollIntoView(ScrollIntoViewOptions)
and {scrollMode: 'if-needed' | 'always'}
.
- new docs page.
- upgrade cypress to be all TS.
- upgrade next.js to follow TS best practice.
- upgrade next.js to export test pages when cypress is running it.
- update readme.
- rewrite old tests to new changes.
- migration guide with a list over breaking changes.
- new rollup build that generates react-router like suite of bundles so this package is easier to consume for most people.
-
{scrollMode: 'if-needed'}
, this feature is what spawned the creation of this package, but it needs to be rewritten to simply check if something isn't visible before it should optimistically attempt scrolling it into view (reference implementations: 1) -
{scrollMode: 'always'}
, and suddenly this package became a lot more useful. -
{block: 'start'}
-
{block: 'center'}
-
{block: 'end'}
-
{block: 'nearest'}
-
{inline: 'start'}
-
{inline: 'center'}
-
{inline: 'end'}
-
{inline: 'nearest'}
- scroll it yourself
{behavior: (scrollInstructions: [Element, scrollTop, scrollLeft])}
. Maybe you want to be creative, or a different transition, easing, do it in a sequence or throttle it. Whatever floats your boat. -
{behavior: 'smooth'}
(ensure ponyfilled animation matches what firefox and chrome is doing, it must not feel slow or odd). -
{boundary: Element}
, limit propagation of scrolling as it traverses innermost to outermost scrolling boxes by passing in an element reference. -
{boundary: (el: Element) => boolean}
, provide a way to do custom checks. This solves the problem with cross-realm elements (scrolling up iframes and frames) where referencial checks won't work. It also provides an escape hatch for userland business logic like "skip all elements that are overflow: hidden".
Testing strategy
- basic one layer tests for
scrollMode
,block
andinline
. - 2 layer tests (scrollbox within scrollbox) for
scrollMode
,block
andinline
. - 3 layer tests (scrollbox within scrollbox, and another one) for
scrollMode
,block
andinline
. - add
writing-mode
test, though we might have to skip making it pass in the initial release. -
boundary
test, should let you set the innermost scrolling box as boundary so unnecessary traversing up the tree can be completely avoided (awesome for performance). -
boundary
callback test, use to test that scrolling cross an iframe boundary (different realm) can work correctly. -
ponyfill smooth
test that the promise it returns can be awaited on correctly, and that errors don't end up in unhandled promise rejections. -
ponyfill smooth
should be cancellable, add the test even if the problem itself won't be solved in time for first release. - downshift-js/downshift#259 ensure tests in this library pass, add tests from there as needed to make that happen.
- Create tests from references in the WebKit repo: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
- and chromium: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
- gecko (my favorite, by far): 1, 2, 3, 4
- same origin test to avoid abuse: https://bugs.chromium.org/p/chromium/issues/detail?id=819314&q=scrollintoView&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
- svg rectangular elements edge case: https://bugs.chromium.org/p/chromium/issues/detail?id=803440&q=scrollintoView&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
- border edge case https://github.com/chromium/chromium/blob/f18e79d901f56154f80eea1e2218544285e62623/third_party/WebKit/LayoutTests/fast/scroll-behavior/bordered-container-child-scroll.html
Helpful reference material
http://www.performantdesign.com/2009/08/26/scrollintoview-but-only-if-out-of-view/
https://github.com/iamdustan/smoothscroll/blob/master/src/smoothscroll.js
Using FireFox' implementation as reference
The way FireFox handles smooth scrolling, and the scrollIntoView features in general is the best one today. So I am using their C++ implementation to guide me on the JS implementation: https://github.com/mozilla/gecko/blob/03abe3240ab1ad8c2e7f78ebb16a6bd3c17febb1/layout/base/PresShell.cpp#L3626-L3743
Rationale from dropping Element.scrollIntoViewIfNeeded
The fine folks over at chromium are already discussing removing this non-standard api: https://bugs.chromium.org/p/chromium/issues/detail?id=699843&q=scrollintoView&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
It's time to move on 😃