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

Autoscrolling improvements #140

Merged
merged 13 commits into from
Mar 25, 2021
Merged

Autoscrolling improvements #140

merged 13 commits into from
Mar 25, 2021

Conversation

clauderic
Copy link
Owner

@clauderic clauderic commented Mar 18, 2021

Fixes #23

Auto-scrolling defaults have been updated, which should generally lead to improved user experience for most consumers.

The auto-scroller now bases its calculations based on the position of the pointer rather than the edges of the draggable element's rect by default. This change is aligned with how the native HTML 5 Drag & Drop auto-scrolling behaves.

This behaviour can be customized using the activator option of the autoScroll prop:

import {AutoScrollActivator, DndContext} from '@dnd-kit/core';

<DndContext autoScroll={{activator: AutoScrollActivator.DraggableRect}} />;

The auto-scroller now also looks at scrollable ancestors in order of appearance in the DOM tree, meaning it will first attempt to scroll the window, and narrow its focus down rather than the old behaviour of looking at scrollable ancestors in order of closeness to the draggable element in the DOM tree (reversed tree order).

This generally leads to an improved user experience, but can be customized by passing a configuration object to the autoScroll prop that sets the order option to TraversalOrder.ReversedTreeOrder instead of the new default value of TraversalOrder.TreeOrder:

import {DndContext, TraversalOrder} from '@dnd-kit/core';

<DndContext autoScroll={{order: TraversalOrder.ReversedTreeOrder}} />;

The autoscrolling thresholds, acceleration and interval can now also be customized using the autoScroll prop:

import {DndContext} from '@dnd-kit/core';

<DndContext
  autoScroll={{
    threshold: {
      // Left and right 10% of the scroll container activate scrolling
      x: 0.1,
      // Top and bottom 25% of the scroll container activate scrolling
      y: 0.25,
    },
    // Accelerate slower than the default value (10)
    acceleration: 5,
    // Auto-scroll every 10ms instead of the default value of 5ms
    interval: 10,
  }}
/>;

Finally, consumers can now conditionally opt out of scrolling certain scrollable ancestors using the canScroll option of the autoScroll prop:

import {DndContext} from '@dnd-kit/core';

<DndContext
  autoScroll={{
    canScroll(element) {
      if (element === document.scrollingElement) {
        return false;
      }

      return true;
    },
  }}
/>;

@changeset-bot
Copy link

changeset-bot bot commented Mar 18, 2021

🦋 Changeset detected

Latest commit: cc13c98

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@dnd-kit/core Major
@dnd-kit/sortable Major
@dnd-kit/modifiers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2021

Size Change: +1.94 kB (+2%)

Total Size: 84.5 kB

Filename Size Change
packages/core/dist/core.cjs.development.js 25.4 kB +644 B (+3%)
packages/core/dist/core.cjs.production.min.js 13.2 kB +426 B (+3%)
packages/core/dist/core.esm.js 25.2 kB +643 B (+3%)
packages/sortable/dist/sortable.cjs.development.js 4.32 kB +92 B (+2%)
packages/sortable/dist/sortable.cjs.production.min.js 2.72 kB +42 B (+2%)
packages/sortable/dist/sortable.esm.js 4.2 kB +91 B (+2%)
ℹ️ View Unchanged
Filename Size Change
packages/accessibility/dist/accessibility.cjs.development.js 979 B 0 B
packages/accessibility/dist/accessibility.cjs.production.min.js 637 B 0 B
packages/accessibility/dist/accessibility.esm.js 847 B 0 B
packages/accessibility/dist/index.js 148 B 0 B
packages/core/dist/index.js 141 B 0 B
packages/modifiers/dist/index.js 144 B 0 B
packages/modifiers/dist/modifiers.cjs.development.js 838 B 0 B
packages/modifiers/dist/modifiers.cjs.production.min.js 574 B 0 B
packages/modifiers/dist/modifiers.esm.js 766 B 0 B
packages/sortable/dist/index.js 144 B 0 B
packages/utilities/dist/index.js 144 B 0 B
packages/utilities/dist/utilities.cjs.development.js 1.63 kB 0 B
packages/utilities/dist/utilities.cjs.production.min.js 962 B 0 B
packages/utilities/dist/utilities.esm.js 1.55 kB 0 B

compressed-size-action

@clauderic clauderic changed the title Scrolling improvements Autoscrolling improvements Mar 18, 2021
@clauderic clauderic marked this pull request as ready for review March 18, 2021 21:50
@ranbena
Copy link
Contributor

ranbena commented Mar 20, 2021

@clauderic I want to try this branch out in my project that uses dnd-kit, but not sure how to point to it, instead of the installed npm @dnd-kit/core package.
How does one achieve this? With yarn link? With a lerna command?

@clauderic
Copy link
Owner Author

You can try using yalc or just straight up building the branch locally and replacing the distributed assets in your project's local node_modules if you just want to quickly test without setting up anything complicated.

This PR is still a bit of a work in progress, the acceleration and thresholds need a bit of polish. Also considering letting consumers pass in their own autoscroller offsets


useEffect(() => {
if (disabled || !scrollableAncestors.length || !draggingRect) {
if (disabled || !scrollableAncestors.length || !pointerCoordinates) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if it's intended, but it looks possible that sortScrollableAncestors could remove elements. Does it make sense the check the sorted ancestors list instead?

Suggested change
if (disabled || !scrollableAncestors.length || !pointerCoordinates) {
if (disabled || !sortedScrollableAncestors.length || !pointerCoordinates) {

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yeah, I realized that could be an unintended consequence of giving consumers a method as flexible as sortedScrollableAncestors. I've since refactored this approach to only give consumers the option decide whether to set the scroll order to the tree order or reversed tree order 800b2d6

Copy link
Contributor

Choose a reason for hiding this comment

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

What if you accept a sort function instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

Semi related to this change... is (or will) there be a way to stop an element scrolling?
When I first saw this PR I was thinking I could use it to stop the window scrolling horizontally, which is an issue I'm facing now with a vertical-only scrolling list.

Copy link
Owner Author

@clauderic clauderic Mar 24, 2021

Choose a reason for hiding this comment

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

What if you accept a sort function instead?

I'd prefer to limit the use-cases here for now, can't really think of good use-cases where you would want to scroll ancestors in an order that doesn't match the DOM (reversed or otherwise).

Semi related to this change... is (or will) there be a way to stop an element scrolling?

I hadn't considered that use-case, but that could certainly be added.

Scroll ancestors are necessary in a few places in the library for collision detection to work properly, so I'd prefer to only let consumers decide if a given ancestor can be scrolled.

Something like:

// canScroll(scrollAncestor: Element): boolean;

<DndContext autoScroll={{
  enabled: true,
  order: TraversalOrder.ReversedTreeOrder,
  canScroll(element) {
    if (element === document.scrollingElement) {
      return false;
    }

    return true;
  }
}} />

Copy link
Contributor

Choose a reason for hiding this comment

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

This looks good to me and I agree on the sorting 👍

@clauderic clauderic force-pushed the scrolling-improvements branch 2 times, most recently from d2feb26 to 18bcbae Compare March 24, 2021 04:14
@clauderic clauderic force-pushed the scrolling-improvements branch 3 times, most recently from 68b3c4e to 20f2475 Compare March 25, 2021 00:52
@clauderic clauderic merged commit 8583825 into master Mar 25, 2021
@clauderic clauderic deleted the scrolling-improvements branch March 25, 2021 01:03
@andelkocvjetkovic
Copy link

Hello, I had issues with autoScroll.thresholds after hours and hours debugging I found out that it is autoScroll.threshold, without s.

autoScroll={{
	threshold: {
	  x: 0,
	  y: 0.02,
	},
}}

@rsshilli
Copy link

rsshilli commented Nov 10, 2021

@andelkocvjetkovic Thank you. You saved my sanity.

@clauderic Maybe you could consider editing your first comment above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve auto-scrolling for small containers / large drag sources
5 participants