🎧🎶 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 Draggable
s #511
react-beautiful-dnd
now supports the combining of Draggable
s 🤩
- 👩🔬 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 Draggable
s while dragging #484
react-beautiful-dnd
now supports the adding and removing of Draggable
s during a drag. This is a powerful feature that unlocks a lot of behaviors
Lazy loading | Trees! (Read more below) |
---|---|
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 |
---|---|---|---|
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.
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 aDraggable
(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 |
---|---|
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) |
---|---|
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
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!
Hooks
→ Responders
Hooks
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 usingflow
orTypeScript
. 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 Responder
s 🕵️♀️
The values provided to the Responders
now has some new information!
DragStart
now contains mode
DragStart
is supplied toonDragStart
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 toonDragUpdate
DropResult
is supplied toonDragEnd
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
at60fps
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
anindex
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
index
es need to be dense and start from0
#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:
- @LukeHendrick (Glitch app) #688
- @rokborf: natural-drag-animation-rbdnd
- @ng-hai: simple trello project #878
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:
- Atlassian
- Confluence
- Balazs Nagy
- Bogdan Chadkin
- Samuel Attard (build ninja)
- Jacob Miller
- Ben Conolly
- Pavithra Kodmad
- Jeniffer Heng
- Ajay Mathur
- Raja Bellebon
- Luke Batchelor
- Pete Gleeson
- Jared Crowe
- React Sydney ⚛️
- Flame photo in cover Joshua Newton