react-beautiful-dnd Changelog

10.1.0

beautiful-by-jake-small

🎧🎢 Release notes designed to be listed to with: "Once there were dragons" @ 4:05

Highlights πŸ€Ύβ€β™€οΈ

  • πŸ‘©β€πŸŽ¨ Stunning animation improvements
  • πŸ“– Overhauled documentation
  • πŸ“± More predictable touch dragging
  • 🏠 Simplified home list styling
  • πŸ’… New project design
  • πŸ“ Blogs of our learnings

Beautiful πŸ”

This release pushes react-beautiful-dnd to new summits of interaction design.

We have removed instant movement (snapping) when moving between lists. Snapping breaks the visual language of moving physical objects around that react-beautiful-dnd is trying to emulate.

βœ… No snapping when moving between lists

refreshed-example-2

❌ This is what it used to be (snapping in the 🏠 home list after a drop)

slow-snapping

You do not need to do anything to get the new animation pattern. I have marked this change as a feature release as it is new design behaviour.

Blog: Beautiful interactions πŸ“

There was a huge amount of work to remove snapping when moving between lists. Who would have thought? Not me πŸ₯΅. I wrote a blog which goes over the journey of this feature in depth. Personally, I think it well worth your time!

πŸ“Blog β†’ Beautiful interactions: Crafting elegant and robust drag and drop animations

New logo πŸ‘©β€πŸŽ¨

logo-migration

We have moved to a logo that encapsulates the playfulness and delight that we are striving for with react-beautiful-dnd

Blog: Logo creation πŸ“

Maryanne Nguyen, a very talented designer at Atlassian, has detailed her creative process in creating the new react-beautiful-dnd logo in a blog 🎨

πŸ“Blog β†’ maryannemade: react-beautiful-dnd logo

More predictable touch dragging πŸ“±

react-beautiful-dnd tries to respect standard browser interactions as much as possible. Currently, the library plays well with force touch interactions:

If the user force presses on the element before they have moved the element (even if a drag has already started) then the drag is cancelled and the standard force press action occurs. For an anchor, this is a website preview.

Unfortunately, heavy presses can cancel a drag. It can be tricky at times to get the right amount of pressure to correctly use touch dragging. This can be frustrating for users.

We have added an option for you to opt-out of respecting force touch interactions. This option will disable force press interactions on the drag handle. However, it allows for a more consistent touch dragging interaction.

We have added shouldRespectForceTouch as a prop to <Draggable />. It defaults to true in order to respect force touch interactions, but you can set it to false to opt out of respecting force touch

<Draggable
  draggableId="draggable"
+ shouldRespectForceTouch={false}
>

</Draggable>

This change resulted in a feature release. The default behaviour matches the behaviour of previous versions.

Should force touch be respected by default?

Right now shouldRespectForceTouch defaults to true in order to respect browser interactions. However, for this specific use case, I am thinking that the default could be to not respect force touch in order to have a more consistent touch dragging experience out of the box.

I have created a request for discussion to collect other people's thoughts on what the default should be.

Simplified home list styling 🏠

We have added a new value to the DroppableStateSnapshot: draggingFromThisWith

type DroppableStateSnapshot = {|
  isDraggingOver: boolean,
  draggingOverWith: ?DraggableId,
+ draggingFromThisWith: ?DraggableId,
|};

draggingFromThisWith is populated with the draggableId of the dragging item in the 🏠 home list for the entire drag. This allows you to style the home list differently from the other lists if you like. We recommend you do this to make it clear which list the user is dragging from. You can read more about the thinking behind this in my blog

In this example we set the background-color of the home list to pink when we are dragging over the list. We set the background-color of the home list to blue when not dragging over the home list.

no-placeholder-when-over-no-list

Overhauled documentation πŸ“–

We have totally overhauled our documentation to be easier to find and use information.

Our README.md was getting too big. It was hard for new comers to know where to start, and it was hard for consumers of the library to quickly find information. We have simplified our README.md and added a comprehensive documentation section which links off to categories of information.

The README.md now contains a high-level introduction to the project, feature set, how to get started and then links to the rest of the documentation.

For new comers and evaluators πŸ‘Ά

Information in the README.md:

  • Big gif showing off what the library is about
  • Reduced badges to the critical subset to reduce noise
  • High level motivation of the project
  • Feature set and limitations
  • Getting started guide
  • An About section which links off information useful to understand, evaluate and get started with the library.

For consumers πŸ‘©β€πŸŽ€

  • The documentation has been broken down into more logical independent chunks to make it clearer where to find topical information. Previously API was under a wall of design thinking information which would not be useful to a non-evaluator
  • All documentation pages have a link back to the documentation root for quickly jumping around

Documentation engineering health πŸ‘¨β€βš•οΈ

  • Added a test to ensure that there are no more broken links πŸŽ‰. This is by far the cause of the most issues
  • Added test to ensure consistent usage of component names
  • Added test to ensure all documentation pages end with a backlink to the documentation root

Refreshed examples πŸ¦Έβ€β™‚οΈ #1096

We have made our examples brighter and more colourful

Previous New style
old style new style

We have also upgraded to Storybook v5 and added our new logo to the header

new style

Other improvements

  • Only attaching to the redux devtools when process.env.NODE_ENV === 'development' #1085. Thanks @teleaziz!!
  • More collision engine refinements

Fixes πŸ›

  • A transition for a property other than transform that finished during a drop animation on a Draggable could cause the drop to end suddenly #1096
  • position:fixed lists on ie11 #1091 #1088. Thanks @InvisibleBacon for raising this one
  • Typo in docs #1102. Thanks @jDeppen

Engineering health

  • Upgraded to flow 0.94 #1119
  • Upgrade of all dev dependencies #1119
  • Moved example website to use emotion πŸ‘©β€πŸŽ€ #1128
  • Moving browser tests to cypress.io. Also added a few more browser tests #1122

cypress

Happy new year! πŸŽ‰

I have been off for a month and I had a great time. I could go for another month...

Here is what we plan on working on next: Up next milestone

Also, a reminder that we have two planned breaking changes coming up:

  • Moving to a React peer dependency of 16.6+ #984
  • Moving from flow to TypeScript #982. This might not be a breaking change if we have a good flow story 🀞

Unplanned but possible:

  • Going all in on hooks and creating a new hook based api πŸ€πŸ˜…

Improvements

doctype warning πŸ‘¨β€βš•οΈ #1068

We have added a dev only warning to notify you if the pages doctype is supported #1068 #1040. We only support the html5 doctype (<!doctype html>). The doctype impacts a number of measurement calculations. Previously if you used another doctype things might work, but there could be some strange issues depending on your css configuration (eg if you did not have body height: 100%). Rather than trying to account for every strange doctype out there - we print a dev warning to the console! 😊 We also now call this out in the docs.

My hope is that this change makes it easier to fall into the pit of success

Just a public service announcement: if you do not add a doctype tag, browsers will use some other doctype such as "Quirks mode". Please add a doctype to your pages!

<!doctype html>

Other

Engineering health

  • Upgrading dev dependencies #1065
  • Upgrading to flow 0.91 #1065

Improvements

πŸ• Delicious auto scrolling #349

Previously when a user picked up a draggable item that was near the edge of a scrollable area it could trigger a large and jarring auto scroll. We have created a solution that gets around this problem in a really elegant way.

I have created a video which goes over what we did in a bit of detail πŸ“Ί

video thumnail

A big thank you to @ajaymathur and @jjcm for their huge help with this one

❀️ Docs

  • New: Common setup guide: Common setup issues that are hard for us to catch in code. We also linked to this from our ISSUE_TEMPLATE.md
  • New: Identifiers guide: How to use identifiers (draggableId and droppableId) successfully in react-beautiful-dnd
  • Fixing typo in README.md link #970. Thanks @fzembow!!
  • Fixing links #955. Thanks @Blasz!!
  • Removing outdated reference to Draggable > type #952. Thanks @DmitryGonchar!!
  • Fixing incorrect drop animation naming in our drop animation guide

Other

  • Avoiding extra DOM read for Droppables #966. Thanks @woohling!
  • Adding extra dev only checks for Draggable and Droppable boolean props #945.

πŸ‘‹ Remember: null is not a valid boolean prop type. Either pass in true, false or undefined to get the React defaultProp value.

πŸ‘©β€βš•οΈ Engineering health

  • Adding additional server-side rendering test to ensure that client hydration works correctly #960. Thanks @petegleeson for the prior work on this
  • Fixed flaky builds on CircleCi caused by flow crashing. Thanks @TrySound for your help with this one! #1008 #1007
  • Moved to flow 0.88
  • Moved to storybook 4x #989
  • Moved back from emotion to my first love: styled-components 4x for examples.
  • Upgrading dev dependencies #1005

πŸ“£ Announcement: breaking change coming

We have two planned breaking changes coming up in early 2019:

  • Moving to a React peer dependency of 16.6+ #984
  • Moving from flow to TypeScript #982

My hope is to batch these two breaking changes into a single breaking change release

Fixes

Improvements

  • Improved cross axis movement into an empty list #936. Allows for movement of bigger items into a list that might not have enough current space for it. Thanks @lukyth for raising this one!
  • Even more spacing accuracy for different box model configurations #919. Also created a spacing stress test example
  • Adding more detail to issue creation template #934
  • Removing unneeded Array.prototype.find message from docs #933. Thanks @wuweiweiwu!
  • Adding note about styled-components 4.0 api change to docs #926. Thanks @balonsom!!
  • Improvements to README.md #943

Fixes

  • Now correctly forwarding component flow types #910. Previously they were being lost in a HOC. Huge thank you to @TrySound for this one! He also added a flow test to ensure there is no regressions on this πŸ‘
  • Fixed misaligned cross-axis drop placement and keyboard movement in some cases #913 #918

marketing

🎧🎢 Release notes designed to be listed to with Angus & Julia Stone - Chateau (ARTY Remix)

Release at a glance 🀩

πŸš€ 30% faster πŸ’₯ smarter collision engine 🎹 more robust keyboard movement system 🎳 new: combine items 🐣 new: add and remove items during a drag 🌲 new: tree library @atlaskit/tree by @Confluence

I know right!? Pretty awesome!! Okay, lets get into the details

✌️ Low risk breaking change 9.x β†’ 10.x

This release is a listed as a breaking change πŸ’₯. However, the risk of actual breakage is very low. Most consumers should be able to upgrade without any issues πŸ‘. We will call out any breaking changes in these releases notes.

Features

Combining Draggables #511

react-beautiful-dnd now supports the combining of Draggables 🀩

combining

  • πŸ‘©β€πŸ”¬ Designed to work intuitively in conjunction with reordering
  • πŸ•Ί Works on both the vertical and horizontal axis
  • 🎹 Full keyboard support
  • ♿️ English screen reader messaging baked in. (You can override the defaults - see our screen reader guide)

We have created a combining guide which will show you how you can use the new feature and the thinking behind it.

I am biased, but the combining guide is really worth a read! The logic for doing combining in conjunction with reordering is very cool

Add and remove Draggables while dragging #484

react-beautiful-dnd now supports the adding and removing of Draggables during a drag. This is a powerful feature that unlocks a lot of behaviors

Lazy loading Trees! (Read more below)
lazy-loading 2018-11-01 17_01_21 hover_to_expand

We have created a guide to help you use this new feature.

New tree library: @atlaskit/tree πŸŒ²πŸŽ‰

In conjunction with this release, we have also released a new tree library: @atlaskit/tree!!! πŸŽ‰ It is a beautiful and accessible tree implementation built on top of react-beautiful-dnd

  • Display and interact with your own tree structure
  • Mouse 🐭, touch πŸ“± and keyboard support 🎹
  • Dropping on a closed group will add the dragging item to the group
  • Dragging over a collapsed group will expand the group after a small timer
  • Dragging an expanded group will collapse the group as the drag starts
  • Lazy loading of subtrees
  • Does not render any DOM ❀️
Hover to expand Drop onto expanded parent Drop onto collapsed parent Drop on another item to create new group
hover_to_expand drop_onto_expanded_parent drop_onto_collapsed_parent drop_to_nest

Improvements

πŸš€ Speed

We have significantly improved the performance of react-beautiful-dnd.

  • 🀘 30% more frames when dragging
  • 🀩 66% more frames for drop animations in low resource environments

You can read about how we did this in our blog "Grabbing the flame πŸ”₯"

πŸ’₯ Smarter collision engine

Our collision engine has been rebuilt in order to take into account:

  • the direction a user is currently moving in, and
  • what items are currently displaced

This results in a much more consistent and natural movement experience.

collision

There was a flaw in the previous engine where edge detection did not consider what was already displaced.

The collision engine is now aware of displacement and so will now always shift items when the visible center goes over the visible edge of an item - even if the visible edge is displaced.

The collision engine is also now aware of the direction a user is currently moving in which is used to facilitate our new combining mode.

🎹 More robust keyboard movement system

The internal keyboard movement system has been completely rebuilt to provide more spacing flexibility and resilience. Improvements:

  • Drastically improved spacing flexibility. Can now use margin safely on any edge of a Draggable (as long as it does not lead to margin collapsing between items) #201
  • Moving from a patch based system, where each movement patches the previous one, to a system where every movement is computed from scratch based on the current displacement. This also means the algorithm is self healing. If a movement ever looks off (which it shouldn't), then the next move will correct the misalignment
  • The new placement system is now what we use to calculate drop placements for consistency
Example of old spacing issue Now handled correctly
beautiful-dnd margin-fix

More drop animation control

We have moved to using only CSS for the drop animation for performance reasons (you can read more about that in "Grabbing the flame πŸ”₯").

As a side benefit of this you are now able to tweak the drop animation, or opt out of it completely. We recommend not opting out the drop animation as it is important communication for the user.

Your own animation No animation (not recommended)
custom-drop-animation no-drop-animation

We have created a drop animation guide to assist you

Cleaner development build messaging

We have made our development build warnings and error message prettier and more informative

logging

We only long warnings if there are actual setup issues (not just for fun!). That said, if you want to, you are now able to disable all warnings:

// disable all development only warnings
window['__react-beautiful-dnd-disable-dev-warnings'] = true;

We have also added tests to ensure that these messages are correctly dropped from production builds.

Better ie11 support #320 #724

Previously we required consumers to polyfill Array.prototype.find in order for react-beautiful-dnd to work in ie11. We now bake in our own light ponyfills so that you are not required to polyfill anything to use react-beautiful-dnd in ie11

πŸ”¬ Smaller

react-beautiful-dnd 10.0.0 is actually a little bit smaller than 9.x. Which is amazing considering how many new capabilities the library has!

screen shot 2018-11-12 at 11 35 23 am

Hooks β†’ Responders

DragDropContext > Responders DragDropContext > Responders

Recently React announced a new alpha Hooks API. To avoid overloading the term Hook and confusing people, we have replaced our usage of the word Hook to Responder. The names of the actual Hooks Responders are unchanged:

  • onBeforeDragStart
  • onDragStart
  • onDragUpdate
  • onDragEnd

This is a type name change, as well as changing how we refer to them in the docs.

-type HookProvided = {|
+type ResponderProvided = {|
  announce: Announce,
|};

-type OnBeforeDragStartHook = (start: DragStart) => mixed;
+type OnBeforeDragStartResponder = (start: DragStart) => mixed;

-type OnDragStartHook = (
+type OnDragStartResponder = (
  start: DragStart,
  provided: ResponderProvided,
) => mixed;

-type OnDragUpdateHook = (
+type OnDragUpdateResponder = (
  update: DragUpdate,
  provided: ResponderProvided,
) => mixed;

-type OnDragEndHook = (
+type OnDragEndResponder = (
  result: DropResult,
  provided: ResponderProvided,
) => mixed;


-type Hooks = {|
-  onBeforeDragStart?: OnBeforeDragStartHook,
-  onDragStart?: OnDragStartHook,
-  onDragUpdate?: OnDragUpdateHook,
-  // always required
-  onDragEnd: OnDragEndHook,
-|};
+type Responders = {|
+  onBeforeDragStart?: OnBeforeDragStartResponder,
+  onDragStart?: OnDragStartResponder,
+  onDragUpdate?: OnDragUpdateResponder,
+  // always required
+  onDragEnd: OnDragEndResponder,
+|};

This is a breaking change πŸ’₯. But it should be a fairly trivial type rename if you are using flow or TypeScript. This would only impact you if you are directly importing the types:

- // this would now break:
-import type { OnDragStartHook } from 'react-beautiful-dnd`

+// need to use the new type name:
+import type { OnDragStartResponder } from 'react-beautiful-dnd`

Responder timings

In order to improve consistency we now force onDragStart and onDragUpdate to be in the tick after the snapshot values are updated. Previously there were in the same tick. We do this to ensure there is a full React render before calling the hooks. This was generally the case anyway so consumers should not be impacted. I found some very edge case scenarios where onDragStart could be batched into the same render pass by React as a snapshot update.

You can read all the timing details in our Responder guide.

This could be classified as a breaking change πŸ’₯, although the risk of breakage is almost nothing. In fact, it fixed a bug we found in one case πŸ€·β€

More information in Responders πŸ•΅οΈβ€β™€οΈ

The values provided to the Responders now has some new information!

DragStart now contains mode

DragStart is supplied to onDragStart

type DragStart = {|
  draggableId: DraggableId,
  type: TypeId,
  source: DraggableLocation,
+ mode: MovementMode,
|};

+ type MovementMode = 'FLUID' | 'SNAP';

There are two seperate modes that a drag can be in

  • 'FLUID': everything is done in response to highly granular input (eg mouse)
  • 'SNAP': items move in response to commands (eg keyboard)

    SNAP may also include our new programmatic dragging mode we have planned #162

DragUpdate (and DragResult) now contain combine

DragUpdate is supplied to onDragUpdate DropResult is supplied to onDragEnd

In order to facilitate the new combining mode a DragUpdate and DragResult now contain combine information

type DragUpdate = {|
  ...DragStart,
  // may not have any destination (drag to nowhere)
  destination: ?DraggableLocation,
+  // populated when a draggable is dragging over another in combine mode
+  combine: ?Combine,
|};

+ // details of the item that is being combined with
+ type Combine = {|
+   draggableId: DraggableId,
+   droppableId: DroppableId,
+ |};

// DropResult gets these too it it extends DragUpdate

type DropResult = {|
  ...DragUpdate,
  reason: DropReason,
|};

New data for a Draggable πŸ‘¨β€πŸŽ¨

We now provide your Draggable with more information for you to use!

type DraggableStateSnapshot = {|
  isDragging: boolean,
  isDropAnimating: boolean,
  draggingOver: ?DroppableId,
+  // Information about a drop animation
+  dropAnimation: ?DropAnimation
+  // the id of a draggable that you are combining with
+  combineWith: ?DraggableId,
+  // a combine target is being dragged over by
+  combineTargetFor: ?DraggableId,
+  // What type of movement is being done: 'FLUID' or 'SNAP'
+  mode: ?MovementMode,
|};

+ // information about a drop animation that you can patch if you like
+ type DropAnimation = {|
+   duration: number,
+   curve: string,
+   moveTo: Position,
+   opacity: ?number,
+   scale: ?number,
+ |};

Moved to CSS for the drop animation

As mentioned previously, we have moved to using a CSS animation for our drop animation. We where able to maintain the exact same visual animation using CSS as we where with a spring based animation. You can read more about this in "Grabbing the flame πŸ”₯".

Breaking change πŸ’₯. We previously rendered a Draggable at 60fps to get it to its home location. Now we let CSS do it. If you were patching the drop animation then this change will break you. Good news, it will now be much easier for you! Check out our drop animation guide.

Other improvements

  • Throw an error when consumer forgets to pass a Draggable an index prop (a common setup error)
  • No longer throwing an error if trying to announce screen reader messages after a DragDropContext is unmounted. It will now print a dev only warning explaining any problems and how you could avoid dropping screen reader messages #556
  • Added a development only warning to let consumers know if they are not meeting the required React peer dependency version. npm will warn you about this, but we are getting a lot of issues about this. So we decided to bake our own warning into the library
  • Now has partial support for lists in a position:fixed container
  • Mentioning in the docs that indexes need to be dense and start from 0 #892
  • Given the docs a lot of love πŸ“–β€οΈ

Fixes

  • Drag Handle unmount performance #543
  • Aborting and drag due to an error when using ReactDOM.createPortal could cause the drag to lock
  • Preventing cross axis movement to invisible locations
  • Cross axis movement will now align correctly when entering the last position of a list #785
  • Auto scrolling shudder when near the end of a scrollable list #764
  • A cross axis move that results in a shift in window scroll is now accounted for

Engineering health

  • Added test to ensure consistent file naming within repo
  • Added test to ensure all developer warnings and any other console.* statements are removed in production builds
  • Added test to ensure styles applied to selectors are valid and pass stylelint
  • Upgrade to flow 0.86 #851

πŸ‘‹β€οΈ Community documentation

We have a new Community section and Addons section in our docs. If you have something that you would like to submit please pull request.

Thanks to these people who have already added content:

We would like your input

We have a few request for discussion (RFD) issues that would benefit from more input:

  • RFD: What would a React 16.7 hooks api look like? #871
  • RFD: Placement of Responders and flow of data #498

Thanks

This release has been months of hard work in the making. Thank you to everybody who has contributed to, and supported this release. A special thanks to:

Engineering health

  • Moving to babel v7 #590. We have been on the prerelease version of this for a while, and it is great to see version 7 move to a stable release! Thanks @TrySound!
  • Upgrading to flow 0.79.1
  • Upgrading our devDependencies to latest versions #590

Fixes

  • Fixing memory leak when unmounting DragDropContext #720. Thanks @faiwer for finding this one, and for the great issue detail!

Improvements

  • More flexible flow type for DragDropContext > hook functions #695. Thanks @kylehalleman!!!
  • More information in the documentation about using interactive elements (such as button) as drag handles. #704 Thanks @kylehalleman!

Changes

DragDropContext > hook functions now allow you to return a value from your hook function if you want. However, we do not do anything with these returned values. This is also called out in the docs #695

- type OnBeforeDragStartHook = (start: DragStart) => void;
- type OnDragStartHook = (start: DragStart, provided: HookProvided) => void;
- type OnDragUpdateHook = (update: DragUpdate, provided: HookProvided) => void;
- type OnDragEndHook = (result: DropResult, provided: HookProvided) => void;

+ type OnBeforeDragStartHook = (start: DragStart) => mixed;
+ type OnDragStartHook = (start: DragStart, provided: HookProvided) => mixed;
+ type OnDragUpdateHook = (update: DragUpdate, provided: HookProvided) => mixed;
+ type OnDragEndHook = (result: DropResult, provided: HookProvided) => mixed;

Changes

onDragStart: Getting the timing right

Summary: we have made the timings of the DragDropContext > Hook functions more consistent, created a new hook: onBeforeDragStart and created a guide for hooks

We keep having timing issues popping up relating to onDragStart. It can break some use cases if it is called before we update the Draggable and Droppable components, and it can break some use cases if it is called after. Rather than trying to make onDragStart work for both cases we have created a new hook: onBeforeDragStart.

onDragStart, onDragUpdate and onDragEnd are now called consistantly after the Draggable and Droppable components have been updated. If you need to do some work just before Draggable and Droppable components have their initial snapshot values updated, then you can use onBeforeDragUpdate.

We have created a guide for hooks which explains all of the hooks in detail and the timings in which the hooks are called.

This is a breaking change πŸ’₯. It has been listed as a breaking change as it will break consumers who are following our dimension locking table reordering strategry.

Fixes

  • Fixing broken test file name which caused repository cloning errors in some environments #697. There was a backspace character in a filename? I know! Thanks @lukebatchelor for the fix, @TrySound for your input and @pashadow for raising the issue

Improvements

Fixes

  • Fixing issue with flow where a type was being used without being imported #677