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

Fix issues with DragOverlay measuring #427

Merged
merged 4 commits into from
Aug 18, 2021
Merged

Conversation

clauderic
Copy link
Owner

This PR follows-up on #408 and #426

It fixes a number of issues with the measuring strategy for the DragOverlay. The main change is that we need to subtract the transform applied on the DragOverlay node when measuring it, otherwise the returned measurement includes the transforms, which means that the next time we compute the collision rect (by adding the transform to the drag overlay position), the newly calculated collision rect has double transforms, which is incorrect.

@wmain can you test this PR against your branch and confirm that it fixes the issues you were seeing with the original solution?

@changeset-bot
Copy link

changeset-bot bot commented Aug 18, 2021

🦋 Changeset detected

Latest commit: d7a4949

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 Major

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 Aug 18, 2021

Size Change: -231 B (0%)

Total Size: 61.4 kB

Filename Size Change
packages/core/dist/core.cjs.development.js 16.2 kB -101 B (-1%)
packages/core/dist/core.cjs.production.min.js 10.3 kB -19 B (0%)
packages/core/dist/core.esm.js 16 kB -102 B (-1%)
packages/sortable/dist/sortable.cjs.development.js 3.9 kB -4 B (0%)
packages/sortable/dist/sortable.cjs.production.min.js 2.54 kB -3 B (0%)
packages/sortable/dist/sortable.esm.js 3.78 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size
packages/accessibility/dist/accessibility.cjs.development.js 640 B
packages/accessibility/dist/accessibility.cjs.production.min.js 486 B
packages/accessibility/dist/accessibility.esm.js 503 B
packages/accessibility/dist/index.js 148 B
packages/core/dist/index.js 141 B
packages/modifiers/dist/index.js 144 B
packages/modifiers/dist/modifiers.cjs.development.js 837 B
packages/modifiers/dist/modifiers.cjs.production.min.js 613 B
packages/modifiers/dist/modifiers.esm.js 760 B
packages/sortable/dist/index.js 144 B
packages/utilities/dist/index.js 144 B
packages/utilities/dist/utilities.cjs.development.js 1.64 kB
packages/utilities/dist/utilities.cjs.production.min.js 989 B
packages/utilities/dist/utilities.esm.js 1.54 kB

compressed-size-action

@clauderic clauderic marked this pull request as draft August 18, 2021 19:50
droppableRects,
over,
recomputeLayouts,
willRecomputeLayouts,
} = useDndContext();
const containerId = useUniqueId(ID_PREFIX, id);
const useDragOverlay = Boolean(overlayNode.rect !== null);
const useDragOverlay = Boolean(dragOverlay.rect !== null);
Copy link
Contributor

@wmain wmain Aug 18, 2021

Choose a reason for hiding this comment

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

This throws an error on my branch as dragOverlay is undefined.

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 this happens sometimes with breaking TypeScript changes across packages, just re-run yarn start and it'll fix itself (eventually). Haven't had time to prioritize upgrading development tooling but it's on the roadmap.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, kicking it a few times did the trick.

@clauderic
Copy link
Owner Author

I converted this PR to draft because I still need to make a couple tweaks, but it should be good enough for you to give it a try

@wmain
Copy link
Contributor

wmain commented Aug 18, 2021

Looks good on my branch!

@clauderic
Copy link
Owner Author

clauderic commented Aug 18, 2021

Good to hear. Out of curiosity, are you positioning the drag overlay child with transform or margin / padding / top / left?

I'm a bit worried about the amount of complexity it adds to try and support measuring the drag overlay child using getBoundingClientRect() (because it is transformed) and am debating shifting to the getViewRect() method instead, which ignores transforms.

@wmain
Copy link
Contributor

wmain commented Aug 18, 2021

Good to hear. Out of curiosity, are you positioning the drag overlay child with transform or margin / padding / top / left?

I'm a bit worried about the amount of complexity it adds to try and support measuring the drag overlay child using getBoundingClientRect() (because it is transformed) and am debating shifting to the getViewRect(https://github.com/clauderic/dnd-kit/blob/master/packages/core/src/utilities/rect/getRect.ts#L92-L110) method instead, which ignores transforms.

We add display: flex, alignItems: center, and justifyContent: center to the DragOverlay styles.

@clauderic
Copy link
Owner Author

That counts towards offsetTop / offsetLeft so would still be supported (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop)

@wmain
Copy link
Contributor

wmain commented Aug 18, 2021

For my curiosity's sake, which step of computation are you considering shifting? Shouldn't the final rect include transformations and therefore make getBoundingClientRect appropriate?

@clauderic
Copy link
Owner Author

clauderic commented Aug 18, 2021

There are a lot of timing-related concerns with regards to measuring elements that have transforms applied. It requires elaborate orchestration to make sure you measure an element at the appropriate point in time, either before or after transforms are updated.

You can see issues with the current strategy if you navigate to the Multiple containers story and sort with the keyboard. The timing of when the DragOverlay node is measured conflicts with the collision detection logic (there's a race condition between the two).

Before.-.DragOverlay.measured.with.transforms.applied.mp4

These issues aren't impossible to solve, but I'd rather keep the code simple and reliable for now and improve on it later, even if it means not supporting DragOverlay children that are positioned using transforms (for the time being).

After.-.DragOverlay.transform.agnostic.measuring.strategy.mp4

This approach is transform agnostic to keep things simple and reliable. It can be improved later down the road.
@clauderic clauderic marked this pull request as ready for review August 18, 2021 21:33
@clauderic clauderic merged commit f96cb5d into master Aug 18, 2021
@clauderic clauderic deleted the fix-drag-overlay-measuring branch August 18, 2021 21:51
@github-actions github-actions bot mentioned this pull request Aug 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment