# react-beautiful-dnd
**Repository Path**: mirrors_fkhadra/react-beautiful-dnd
## Basic Information
- **Project Name**: react-beautiful-dnd
- **Description**: Beautiful, accessible drag and drop for lists with React.js
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-08
- **Last Updated**: 2026-02-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README

# react-beautiful-dnd
Beautiful, accessible drag and drop for lists with [`React.js`](https://facebook.github.io/react/)
[](https://circleci.com/gh/atlassian/react-beautiful-dnd/tree/master)
[](https://www.npmjs.com/package/react-beautiful-dnd) [](https://david-dm.org/atlassian/react-beautiful-dnd) [](https://greenkeeper.io/) [](http://semver.org/spec/v2.0.0.html)

## Examples 🎉
See how beautiful it is for yourself!
### Viewing on a desktop
[All the examples!](https://react-beautiful-dnd.netlify.com)
### Viewing on a mobile or tablet
- [Simple list](https://react-beautiful-dnd.netlify.com/iframe.html)
- [Board](https://react-beautiful-dnd.netlify.com/iframe.html?selectedKind=board&selectedStory=simple) - best viewed in landscape
> We provide different links for touch devices as currently [storybook](https://github.com/storybooks/storybook) does not have a good mobile menu experience [more information](https://github.com/storybooks/storybook/issues/124)
## Basic usage examples
We have created some basic examples on `codesandbox` for you to play with directly:
- [Simple vertical list](https://codesandbox.io/s/k260nyxq9v)
- [Simple horizontal list](https://codesandbox.io/s/mmrp44okvj)
- [Simple DnD between two lists](https://codesandbox.io/s/ql08j35j3q)
## Core characteristics
- Beautiful, natural movement of items
- Clean and powerful api which is simple to get started with
- Plays extremely well with standard browser interactions
- Unopinionated styling
- No creation of additional wrapper dom nodes - flexbox and focus management friendly!
- Accessible
## Get started 🤩
We have created [a free course on `egghead.io`](https://egghead.io/courses/beautiful-and-accessible-drag-and-drop-with-react-beautiful-dnd) to help people get started with `react-beautiful-dnd` as quickly as possible

## Read this in other languages
- [ **한글/Korean**](https://github.com/LeeHyungGeun/react-beautiful-dnd-kr)
- [ **中文/Chinese**](https://github.com/chinanf-boy/react-beautiful-dnd-zh)
## Currently supported feature set
- Vertical lists ↕
- Horizontal lists ↔
- Movement between lists (▤ ↔ ▤)
- Mouse 🐭, keyboard 🎹 and touch 👉📱 (mobile, tablet and so on) support
- Auto scrolling - automatically scroll containers and the window as required during a drag (even with keyboard 🔥)
- [Multi drag support](/docs/patterns/multi-drag.md)
- Incredible screen reader support - we provide an amazing experience for english screen readers out of the box 📦. We also provide complete customisation control and internationalisation support for those who need it 💖
- Conditional [dragging](https://github.com/atlassian/react-beautiful-dnd#props-1) and [dropping](https://github.com/atlassian/react-beautiful-dnd#conditionally-dropping)
- Multiple independent lists on the one page
- Flexible item sizes - the draggable items can have different heights (vertical lists) or widths (horizontal lists)
- Compatible with semantic table reordering - [table pattern](/docs/patterns/tables.md)
- Compatible with [`React.Portal`](https://reactjs.org/docs/portals.html) - [portal pattern](/docs/patterns/using-a-portal.md)
- Custom drag handles - you can drag a whole item by just a part of it
- A `Droppable` list can be a scroll container (without a scrollable parent) or be the child of a scroll container (that also does not have a scrollable parent)
- Independent nested lists - a list can be a child of another list, but you cannot drag items from the parent list into a child list
- Server side rendering compatible
- Plays well with [nested interactive elements](https://github.com/atlassian/react-beautiful-dnd#interactive-child-elements-within-a-draggable) by default
### Lots more coming soon
You can check out all the features that will be landing soon [on our issue page](https://github.com/atlassian/react-beautiful-dnd/issues).
## Upgrading
We have created upgrade instructions in our release notes to help you upgrade to the latest version!
- [Upgrading from `7.x` to `8.x`](https://github.com/atlassian/react-beautiful-dnd/releases/tag/v8.0.0)
- [Upgrading from `6.x` to `7.x`](https://github.com/atlassian/react-beautiful-dnd/releases/tag/v7.0.0)
- [Upgrading from `5.x` to `6.x`](https://github.com/atlassian/react-beautiful-dnd/releases/tag/v6.0.0)
- [Upgrading from `4.x` to `5.x`](https://github.com/atlassian/react-beautiful-dnd/releases/tag/v5.0.0)
- [Upgrading from `3.x` to `4.x`](https://github.com/atlassian/react-beautiful-dnd/releases/tag/v4.0.0)
## Not for everyone
There are a lot of libraries out there that allow for drag and drop interactions within React. Most notable of these is the amazing [`react-dnd`](https://github.com/react-dnd/react-dnd). It does an incredible job at providing a great set of drag and drop primitives which work especially well with the [wildly inconsistent](https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html) html5 drag and drop feature. **`react-beautiful-dnd` is a higher level abstraction specifically built for vertical and horizontal lists**. Within that subset of functionality `react-beautiful-dnd` offers a powerful, natural and beautiful drag and drop experience. However, it does not provide the breadth of functionality offered by react-dnd. So this library might not be for you depending on what your use case is.
## Driving philosophy: physicality
The core design idea of `react-beautiful-dnd` is physicality: we want users to feel like they are moving physical objects around
### Application 1: no instant movement
It is a fairly standard drag and drop pattern for things to disappear and reappear in response to the users drag. For a more natural drag we animate the movement of items as they need to move out of the way while dragging to more clearly show a drags effect. We also animate the drop of an item so that it animates into its new home position. At no point is an item instantly moved anywhere — regardless of whether it is dragging or not.
### Application 2: knowing when to move
It is quite common for drag and drop interactions to be based on the position that user started the drag from.
In `react-beautiful-dnd` a dragging items impact is based on its centre of gravity — regardless of where a user grabs an item from. A dragging items impact follows similar rules to a set of scales ⚖️. Here are some rules that are followed to allow for a natural drag experience even with items of flexible height:
- A list is _dragged over_ when the centre position of a dragging item goes over one of the boundaries of the list
- A resting drag item will move out of the way of a dragging item when the centre position of the dragging item goes over the edge of the resting item. Put another way: once the centre position of an item (A) goes over the edge of another item (B), B moves out of the way.
### Application 3: no drop shadows
Drop shadows are useful in an environment where items and their destinations snap around. However, with `react-beautiful-dnd` it should be obvious where things will be dropping based on the movement of items. This might be changed in the future - but the experiment is to see how far we can get without any of these affordances.
### Application 4: maximise interactivity
`react-beautiful-dnd` works really hard to avoid as many periods of non-interactivity as possible. The user should feel like they are in control of the interface and not waiting for an animation to finish before they can continue to interact with the interface. However, there is a balance that needs to be made between correctness and power in order to make everybody's lives more sane. Here are the only situations where some things are not interactive:
1. From when a user cancels a drag to when the drop animation completes. On cancel there are lots of things moving back to where they should be. If you grab an item in a location that is not its true home then the following drag will be incorrect.
2. Starting a drag on an item that is animating its own drop. For simplicity this is the case - it is actually quite hard to grab something while it is animating home. It could be coded around - but it seems like an edge case that would add a lot of complexity.
Keep in mind that these periods of inactivity may not always exist.
### Application 5: no drag axis locking
For now, the library does not support drag axis locking (aka drag rails). This is where the user is restricted to only dragging along one axis. The current thinking is this breaks the physical metaphor we are going for and sends a message to the user that they are interacting with a piece of software rather than moving physical objects around. It is possible to ensure that a user can only drop in a single list by using props `type` and `isDropDisabled`. You can also do some visual treatment to the list `onDragStart` to show the user that this is the only place they can interact with.
### Application 6: natural cross list movement
Rather than using an index based approach for keyboard movement between lists, `react-beautiful-dnd` performs cross list movement based on **inertia, gravity and collisions**. You can find out more about how this works by reading the blog ["Natural keyboard movement between lists"](https://medium.com/@alexandereardon/friction-gravity-and-collisions-3adac3a94e19).

## Carefully designed animations
With things moving a lot it would be easy for the user to become distracted by the animations or for them to get in the way. We have tweaked the various animations to ensure the right balance of guidance, performance and interactivity.
### Dropping
When you drop a dragging item its movement is based on physics (thanks [`react-motion`](https://github.com/chenglou/react-motion)). This results in the drop feeling more weighted and physical.
### Moving out of the way
Items that are moving out of the way of a dragging item do so with a CSS transition rather than physics. This is to maximise performance by allowing the GPU to handle the movement. The CSS animation curve has been designed to communicate getting out of the way.
How it is composed:
1. A warm up period to mimic a natural response time
2. A small phase to quickly move out of the way
3. A long tail so that people can read any text that is being animated in the second half of the animation

> animation curve used when moving out of the way
## Caring about the interaction details
### Focus management
`react-beautiful-dnd` does not create any wrapper elements. This means that it will not impact the usual tab flow of a document. For example, if you are wrapping an _anchor_ tag then the user will tab to the anchor directly and not an element surrounding the _anchor_. Whatever element you wrap will be given a `tab-index` to ensure that users can tab to the element to perform keyboard dragging.
### Auto scrolling
When a user drags a `Draggable` near the edge of a _container_ we automatically scroll the container as we are able to in order make room for the `Draggable`.
> A _container_ is either a `Droppable` that is scrollable or has a scroll parent - or the `window`.
| Mouse and touch | Keyboard |
| ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|  |  |
It also works in multi list configurations with all input types
| Mouse and touch | Keyboard |
| ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|  |  |
#### For mouse and touch inputs 🐭📱
When the center of a `Draggable` gets within a small distance from the edge of a container we start auto scrolling. As the user gets closer to the edge of the container we increase the speed of the auto scroll. This acceleration uses an easing function to exponentially increase the rate of acceleration the closer we move towards the edge. We reach a maximum rate of acceleration a small distance from the true edge of a container so that the user does not need to be extremely precise to obtain the maximum scroll speed. This logic applies for any edge that is scrollable.
The distances required for auto scrolling are based on a percentage of the height or width of the container for vertical and horizontal scrolling respectively. By using percentages rather than raw pixel values we are able to have a great experience regardless of the size and shape of your containers.
##### Mouse wheel and trackpads
In addition to auto scrolling we also allow users to scroll the window or a `Droppable` manually using their _mouse wheel_ or _trackpad_ 👌
##### A note about big `Draggable`s
If the `Draggable` is bigger than a container on the axis you are trying to scroll - we will not permit scrolling on that axis. For example, if you have a `Draggable` that is longer than the height of the window we will not auto scroll vertically. However, we will still permit scrolling to occur horizontally.
##### iOS auto scroll shake 📱🤕
When auto scrolling on an iOS browser (webkit) the `Draggable` noticeably shakes. This is due to a [bug with webkit](https://bugs.webkit.org/show_bug.cgi?id=181954) that has no known work around. We tried for a long time to work around the issue! If you are interesting in seeing this improved please engage with the [webkit issue](https://bugs.webkit.org/show_bug.cgi?id=181954).
#### For keyboard dragging 🎹
We also correctly update the scroll position as required when keyboard dragging. In order to move a `Draggable` into the correct position we can do a combination of a `Droppable` scroll, `window` scroll and manual movements to ensure the `Draggable` ends up in the correct position in response to user movement instructions. This is boss 🔥.
This is amazing for users with visual impairments as they can correctly move items around in big lists without needing to use mouse positioning.
### Accessibility
Traditionally drag and drop interactions have been exclusively a mouse or touch interaction. This library ships with support for drag and drop interactions **using only a keyboard**. This enables power users to drive their experience entirely from the keyboard. As well as opening up these experiences to users who would have been excluded previously.
We provide **fantastic support for screen readers** to assist users with visual (or other) impairments. We ship with english messaging out of the box 📦. However, you are welcome to override these messages by using the `announce` function that it provided to all of the `DragDropContext > hook` functions.
See our [screen reader guide](docs/guides/screen-reader.md) for a guide on crafting useful screen reader messaging.
#### Example screen reader behaviour

## Mouse dragging
### Sloppy clicks and click prevention 🐱🎁
When a user presses the mouse down on an element, we cannot determine if the user was clicking or dragging. Also, sometimes when a user clicks they can move the cursor slightly — a sloppy click. So we only start a drag once the user has moved beyond a certain distance with the mouse down (the drag threshold) — more than they would if they were just making a sloppy click. If the drag threshold is not exceeded then the user interaction behaves just like a regular click. If the drag threshold is exceeded then the interaction will be classified as a drag and the standard click behaviour will not occur.
This allows consumers to wrap interactive elements such as an anchor and have it be both a standard anchor as well as a draggable item in a natural way.
(🐱🎁 is a [schrodinger's cat](https://www.youtube.com/watch?v=IOYyCHGWJq4) joke)
> To see more indepth information about how we impact standard browser events see our [how we use DOM events guide](docs/guides/how-we-use-dom-events.md)
### Keyboard shortcuts: mouse dragging
When a drag **is not occurring** `react-beautiful-dnd` does not impact any of the standard keyboard interactions (it has no listeners bound).
When a drag **is occurring** with a _mouse_ the user is able to execute the following keyboard shortcuts:
- **escape** esc - cancel the drag
During a mouse drag the following standard keyboard events are prevented to prevent a bad experience:
- **tab** tab ↹ - preventing tabbing
- **enter** ⏎ - preventing submission
Other than these explicitly prevented keyboard events all standard keyboard events should work as expected.
## Keyboard dragging
`react-beautiful-dnd` supports dragging with only a keyboard. We have audited how our keyboard shortcuts interact with standard browser keyboard interactions. When the user is not dragging they can use their keyboard as they normally would. While dragging we override and disable certain browser shortcuts (such as `tab`) to ensure a fluid experience for the user.
> To see more indepth information about how we impact standard browser events see our [how we use DOM events guide](docs/guides/how-we-use-dom-events.md)
### Keyboard shortcuts: keyboard dragging
When a drag is not occurring, the user will be able to navigate through the `Draggable`'s on a page using the standard **tab** tab ↹ key to move forward through the tabbable elements and (**shift** + **tab**) (shift + )tab ↹) to move backwards. We achieve this by adding a `tab-index` to the `Draggable`. When a `Draggable` has focus the **spacebar** space will **lift** a `Draggable`. This will start the drag.
Once a drag is started the following keyboard shortcuts can be used:
- **spacebar** space - drop the `Draggable`
- **escape** esc - cancel the drag
The following commands are also available but they depend on the `type` of `Droppable` that the `Draggable` is _currently_ in:
#### Within a vertical list
- **Up arrow** ↑ - move a `Draggable` upwards in a `Droppable`
- **Down arrow** ↓ - move a `Draggable` downwards in a `Droppable`
- **Right arrow** → - move a `Draggable` to a `Droppable` to the _right_ of the current `Droppable` (move to new list)
- **Left arrow** ← - move a `Draggable` to a `Droppable` to the _left_ of the current `Droppable` (move to new list)
#### Within a horizontal list
- **Up arrow** ↑ - move a `Draggable` to a `Droppable` to _above_ the current `Droppable` (move to new list)
- **Down arrow** ↓ - move a `Draggable` to a `Droppable` to _below_ the current `Droppable` (move to new list)
- **Right arrow** → - move a `Draggable` to the _right_ in the current `Droppable`
- **Left arrow** ← - move a `Draggable` to the _left_ in the current `Droppable`
During a drag the following standard keyboard events have their default behaviour prevented (through `event.preventDefault()`) to avoid a bad experience:
- **tab** tab ↹ - preventing tabbing
- **enter** ⏎ - preventing submission
## Touch dragging
`react-beautiful-dnd` supports dragging on touch devices such as mobiles and tablets.

> Recorded on iPhone 6s
### Understanding intention: tap, force press, scroll and drag
When a user presses their finger (or other input) on a `Draggable` we are not sure if they where intending to _tap_, _force press_, _scroll the container_ or _drag_. **As much as possible `react-beautiful-dnd` aims to ensure that a users default interaction experience remains unaffected**.
> To see more indepth information about how we impact standard browser events see our [how we use DOM events guide](docs/guides/how-we-use-dom-events.md)
### Starting a drag: long press
A user can start a drag by holding their finger 👇 on an element for a small period of time 🕑 (long press)
### Tap support
If the user lifts their finger before the timer is finished then we release the event to the browser for it to determine whether to perform the standard tap / click action. This allows you to have a `Draggable` that is both clickable such as a anchor as well as draggable. If the item was dragged then we block the tap action from occurring.
### Native scrolling support
If we detect a `touchmove` before the long press timer expires we cancel the pending drag and allow the user to scroll normally. This means that the user needs to be fairly intentional and precise with their grabbing. Once the first `touchmove` occurs we have to either opt in or out of native scrolling.
- If the long press timer **has not** expired: _allow native scrolling and prevent dragging_
- If the long press timer **has** expired: _a drag has started and we prevent native scrolling_
### Force press support
> Safari only
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.
### Vibration
> This is merely an idea - it is up to you to add this if you want this behavior.
If you like you could also trigger a [vibration event](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API) when the user picks up a `Draggable`. This can provide tactile feedback that the user is doing something. It currently is only supported in Chrome on Android.
```js
class App extends React.Component {
onDragStart = () => {
// good times
if (window.navigator.vibrate) {
window.navigator.vibrate(100);
}
};
/*...*/
}
```
## Multi drag
We have created a [multi drag pattern](/docs/patterns/multi-drag.md) that you can build on top of `react-beautiful-dnd` in order to support dragging multiple `Draggable` items at once.

## Preset styles
We apply a number of non-visible styles to facilitate the dragging experience. We do this using combination of styling targets and techniques. It is a goal of the library to provide unopinioned styling. However, we do apply some reasonable `cursor` styling on drag handles by default. This is designed to make the library work as simply as possible out of the box. If you want to use your own cursors you are more than welcome to. All you need to do is override our cursor style rules by using a rule with [higher specificity](https://css-tricks.com/specifics-on-css-specificity/).
Here are the styles that are applied at various points in the drag lifecycle:
### In every phase
#### Always: drag handle
Styles applied to: **drag handle element** using the `data-react-beautiful-dnd-drag-handle` attribute.
A long press on anchors usually pops a content menu that has options for the link such as 'Open in new tab'. Because long press is used to start a drag we need to opt out of this behavior
```css
-webkit-touch-callout: none;
```
Webkit based browsers add a grey overlay to anchors when they are active. We remove this tap overlay as it is confusing for users. [more information](https://css-tricks.com/snippets/css/remove-gray-highlight-when-tapping-links-in-mobile-safari/).
```css
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
```
Avoid the _pull to refresh action_ and _delayed anchor focus_ on Android Chrome
```css
touch-action: manipulation;
```
#### Always: Droppable
Styles applied to: **droppable element** using the `data-react-beautiful-dnd-droppable` attribute.
Opting out of the browser feature which tries to maintain the scroll position when the DOM changes above the fold. We already correctly maintain the scroll position. The automatic `overflow-anchor` behavior leads to incorrect scroll positioning post drop.
```css
overflow-anchor: none;
```
### Phase: resting
#### (Phase: resting): drag handle
Styles applied to: **drag handle element** using the `data-react-beautiful-dnd-drag-handle` attribute.
Adding a cursor style to let the user know this element is draggable. You are welcome to override this.
```css
cursor: grab;
```
### Phase: dragging
#### (Phase: dragging): drag handle element
**Styles applied using the `data-react-beautiful-dnd-drag-handle` attribute**
An optimisation to avoid processing `pointer-events` while dragging. Also used to allow scrolling through a drag handle with a track pad or mouse wheel.
```css
pointer-events: none;
```
#### (Phase: dragging): Draggable element
**Styles applied using the `data-react-beautiful-dnd-draggable` attribute**
This is what we use to control `Draggable`s that need to move out of the way of a dragging `Draggable`.
```css
transition: ${string};
```
**Styles applied using inline styles**
This is described by the type [`DraggableStyle`](https://github.com/atlassian/react-beautiful-dnd#type-information-1).
#### (Phase: dragging): body element
We apply a cursor while dragging to give user feedback that a drag is occurring. You are welcome to override this. A good point to do this is the `onDragStart` event.
```css
cursor: grabbing;
```
To prevent the user selecting text as they drag apply this style
```css
user-select: none;
```
### Phase: dropping
#### (Phase: dropping): drag handle element
**Styles applied using the `data-react-beautiful-dnd-drag-handle` attribute**
We apply the grab cursor to all drag handles except the drag handle for the dropping `Draggable`. At this point the user is able to drag other `Draggable`'s if they like.
```css
cursor: grab;
```
#### (Phase: dropping): draggable
Same as dragging phase
### Phase: user cancel
> When a user explicitly cancels a drag
This is the same as `Phase: dropping`. However we do not apply a `cursor: grab` to the drag handle. During a user initiated cancel we do not allow the dragging of other items until the drop animation is complete.
### Preset styles are vendor prefixed
All styles applied are vendor prefixed correctly to meet the requirements of our [supported browser matrix](https://confluence.atlassian.com/cloud/supported-browsers-744721663.html). This is done by hand to avoid adding to react-beautiful-dnd's size by including a css-in-js library
## Installation
### Package manager
```bash
# yarn
yarn add react-beautiful-dnd
# npm
npm install react-beautiful-dnd --save
```
### Distribution bundle
A [universal module definition](https://github.com/umdjs/umd) bundle is published on `npm` under the `/dist` folder for consumption . We publish the following files:
- `dist/react-beautiful-dnd.js`
- `dist/react-beautiful-dnd.min.js` (minified bundle)
These bundles list `react` as an external which needs to be provided. This is done to reduce the size of the bundle and prevent consumers from loading `react` multiple times. You can provide `react` through your module system or simply by having `react` on the `window`.
You can use the UMD to run `react-beautiful-dnd` directly in the browser.
```html
```
There is also an [example codepen](https://codepen.io/alexreardon/project/editor/ZyNMPo) you can use to play with this installation method.
## [`ClojureScript`](https://clojurescript.org/)
You can consume `react-beautiful-dnd` from within `ClojureScript` using [CLJSJS](https://cljsjs.github.io/)!
## API
Okay, into the fun stuff - so how do you use the library?
## `DragDropContext`
In order to use drag and drop, you need to have the part of your `React` tree that you want to be able to use drag and drop in wrapped in a `DragDropContext`. It is advised to just wrap your entire application in a `DragDropContext`. Having nested `DragDropContext`'s is _not_ supported. You will be able to achieve your desired conditional dragging and dropping using the props of `Droppable` and `Draggable`. You can think of `DragDropContext` as having a similar purpose to the [react-redux Provider component](https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store)
### Props
```js
type Hooks = {|
// optional
onDragBeforeStart?: OnDragBeforeStartHook,
onDragStart?: OnDragStartHook,
onDragUpdate?: OnDragUpdateHook,
// required
onDragEnd: OnDragEndHook,
|};
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;
type Props = {|
...Hooks,
children: ?Node,
|};
```
### Basic usage
```js
import { DragDropContext } from 'react-beautiful-dnd';
class App extends React.Component {
onDragStart = () => {
/*...*/
};
onDragUpdate = () => {
/*...*/
};
onDragEnd = () => {
// the only one that is required
};
render() {
return (
I am a droppable!
{provided.placeholder}
My draggable
I will break things!