# React Beautiful Dnd > Traditionally drag and drop interactions have been exclusively a mouse or touch interaction. This library has invested a huge amount of effort to ensure that everybody has access to drag and drop inte --- # Accessibility โ™ฟ๏ธ Traditionally drag and drop interactions have been exclusively a mouse or touch interaction. This library has invested a huge amount of effort to ensure that everybody has access to drag and drop interactions ## What we do to include everyone - [Full keyboard support](/docs/sensors/keyboard.md) (reordering, combining, moving between lists) - [Keyboard multi drag support](/docs/patterns/multi-drag.md) - Keyboard [auto scrolling](/docs/guides/auto-scrolling.md) - Fantastic [screen reader support](/docs/guides/screen-reader.md) - _We ship with english messaging out of the box ๐Ÿ“ฆ_ - Smart management of [browser focus](/docs/guides/browser-focus.md) - A [Google lighthouse](https://developers.google.com/web/tools/lighthouse) automated build to ensure perfect accessibility scores (at least according to [Google](https://developers.google.com/web/tools/lighthouse/v3/scoring#a11y)) ![screen-reader-text](https://user-images.githubusercontent.com/2182637/36571009-d326d82a-1888-11e8-9a1d-e44f8b969c2f.gif) > Example screen reader announcement [โ† Back to documentation](/README.md#documentation-) --- # 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 We have designed a drop animation that feels weighted and physical. It is based on a [`spring`](https://developer.android.com/guide/topics/graphics/spring-animation) and uses a CSS animation with a dynamic duration to achieve the effect. ![result-curve](https://user-images.githubusercontent.com/2182637/48235467-1ce34200-e412-11e8-8c69-2060a0c2f61a.png) > Animation curve used when dropping. Duration is dynamic based on distance to travel You can tweak the drop animation if you would like to. We have created a guide: [drop animation](/docs/guides/drop-animation.md) ## 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](https://raw.githubusercontent.com/alexreardon/files/master/resources/dnd-ease-in-out-small.png?raw=true) > Animation curve used when moving out of the way [โ† Back to documentation](/README.md#documentation-) --- # Browser support ๐ŸŒ This library supports the standard [Atlassian supported browsers](https://confluence.atlassian.com/cloud/supported-browsers-744721663.html) for desktop: | Desktop | Version | | ------------------------------------ | ---------------------------------------------------- | | Microsoft Internet Explorer(Windows) | Version 11 | | Microsoft Edge | Latest stable version supported | | Mozilla Firefox (all platforms) | Latest stable version supported | | Google Chrome (Windows and Mac) | Latest stable version supported | | Safari (Mac) | Latest stable version on latest OS release supported | | Mobile | Version | | ------------------------ | --------------------------------------------------------- | | Chrome (Android and iOS) | Latest stable version supported | | Mobile Safari (iOS) | Latest stable version supported | | Android (Android) | The default browser on Android 4.0.3 (Ice Cream Sandwich) | [โ† Back to documentation](/README.md#documentation-) --- # Design principles ๐Ÿ“– This page goes over the design and interaction thinking behind `react-beautiful-dnd`. ## Foundational idea: 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 (no snapping) 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: movement to communicate positioning > No support for drop shadows or line markings > _Drop shadow: putting a clone or 'shadow' of the dragging item in the drop location_ `react-beautiful-dnd` relies on movement to communicate positioning. It is trying to create a system that is based on physical metaphores. Drop shadows, lines and other affordances are useful in drag and drop contexts where natural movement is not possible. Drop shadows pose a number of confusing design moments if combined with a natural movement system, including: - Where is the shadow when you are not over a list? - How should it move between items? - How should it appear as you enter a new list? The answer to these is often: snapping (where something just appears in the right spot). We are trying hard to avoid any snapping as it breaks the physicality we are trying to model. ### 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). ![example](https://raw.githubusercontent.com/alexreardon/files/master/resources/collision.gif?raw=true) [โ† Back to documentation](/README.md#documentation-) --- # Examples ๐ŸŽ‰ See how beautiful it is for yourself! ## Viewing on a desktop [All the examples!](https://react-beautiful-dnd.netlify.app) ## Viewing on a mobile or tablet - [Simple list](https://react-beautiful-dnd.netlify.app/iframe.html?id=single-vertical-list--basic) - [Board](https://react-beautiful-dnd.netlify.app/iframe.html?id=board--simple) - best viewed in landscape > We provide different links for touch devices as [storybook](https://github.com/storybooks/storybook) runs examples in an iframe which can result in a strange auto scroll experience ## Basic samples 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) - [Using with function components](https://codesandbox.io/s/zqwz5n5p9x) - [Simple DnD between two lists](https://codesandbox.io/s/ql08j35j3q) - _Community made_ - [Simple DnD between a dynamic number of lists (with function components) and ability to delete items](https://codesandbox.io/s/-w5szl) - _Community made_ [โ† Back to documentation](/README.md#documentation-) --- # Installation [![module formats: umd, cjs, and esm](https://img.shields.io/badge/module%20formats-umd%2c%20cjs%2c%20esm-green.svg?style=flat)](https://unpkg.com/react-beautiful-dnd/dist/) ## General 1. Add the `react-beautiful-dnd` package ```bash # yarn yarn add react-beautiful-dnd # npm npm install react-beautiful-dnd --save ``` 2. Use the package ```js import { DragDropContext } from 'react-beautiful-dnd'; ``` 3. Profit ๐Ÿ•บ ## `React` environment In order to use `react-beautiful-dnd` you will probably want to have a `React` environment set up. - [Add react to a website](https://reactjs.org/docs/add-react-to-a-website.html) - official `React` docs - [Setup a react environment with `create-react-app`](https://egghead.io/lessons/react-set-up-a-react-environment-with-create-react-app) - from our [free getting started course](https://egghead.io/courses/beautiful-and-accessible-drag-and-drop-with-react-beautiful-dnd) ## 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/)! [โ† Back to documentation](/README.md#documentation-) --- # `` 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 ``. It is advised to just wrap your entire application in a ``. Having nested ``'s is _not_ supported. You will be able to achieve your desired conditional dragging and dropping using the props of `` and ``. You can think of `` as having a similar purpose to the [react-redux Provider component](https://react-redux.js.org/api/provider). A content-security-protection nonce attribute is added to the injected style tags if provided. ## Props ```js type Responders = {| // optional onBeforeCapture?: OnBeforeCaptureResponder onBeforeDragStart?: OnBeforeDragStartResponder, onDragStart?: OnDragStartResponder, onDragUpdate?: OnDragUpdateResponder, // required onDragEnd: OnDragEndResponder, |}; import type { Node } from 'react'; type Props = {| ...Responders, // We do not technically need any children for this component children: Node | null, // Read out by screen readers when focusing on a drag handle dragHandleUsageInstructions?: string, // Used for strict content security policies nonce?: string, // Used for custom sensors sensors?: Sensor[], enableDefaultSensors?: ?boolean, |}; ``` - `dragHandleUsageInstructions`: What is read out to screen reader users when a _drag handle_ is given browser focus. See our [screen reader guide](/docs/guides/screen-reader.md) - `nonce`: Used for strict content security policy setups. See our [content security policy guide](/docs/guides/content-security-policy.md) - `sensors`: Used to pass in your own `sensor`s for a ``. See our [sensor api documentation](/docs/sensors/sensor-api.md) - `enableDefaultSensors`: Whether or not the default sensors ([mouse](/docs/sensors/mouse.md), [keyboard](/docs/sensors/keyboard.md), and [touch](/docs/sensors/touch.md)) are enabled. You can also import them separately as `useMouseSensor`, `useKeyboardSensor`, or `useTouchSensor` and reuse just some of them via `sensors` prop. See our [sensor api documentation](/docs/sensors/sensor-api.md) > See our [type guide](/docs/guides/types.md) for more details ## Basic usage ### Using a `class` component ```js import React from 'react'; import { DragDropContext } from 'react-beautiful-dnd'; class App extends React.Component { onBeforeCapture = () => { /*...*/ }; onBeforeDragStart = () => { /*...*/ }; onDragStart = () => { /*...*/ }; onDragUpdate = () => { /*...*/ }; onDragEnd = () => { // the only one that is required }; render() { return (
Hello world
); } } ``` ### Using a `function` component ```js import React from 'react'; import { DragDropContext } from 'react-beautiful-dnd'; function App() { // using useCallback is optional const onBeforeCapture = useCallback(() => { /*...*/ }, []); const onBeforeDragStart = useCallback(() => { /*...*/ }, []); const onDragStart = useCallback(() => { /*...*/ }, []); const onDragUpdate = useCallback(() => { /*...*/ }, []); const onDragEnd = useCallback(() => { // the only one that is required }, []); return (
Hello world
); } ``` ## `Responders` > `Responders` were previously known as `Hooks` Responders are top level application events that you can use to perform your own state updates, style updates, as well as to make screen reader announcements. [Please see our Responders guide](/docs/guides/responders.md) for detailed information about responders โค๏ธ [โ† Back to documentation](/README.md#documentation-) --- # `` `` components can be dragged around and dropped onto ``s. A `` must always be contained within a ``. It is **possible** to reorder a `` within its home `` or move to another ``. It is **possible** because a `` is free to control what it allows to be dropped on it. Every `` has a _drag handle_. A _drag handle_ is the element that the user interacts with in order to drag a ``. A _drag handle_ can be the `` element itself, or a child of the ``. Note that by default a _drag handle_ cannot be an interactive element, since [event handlers are blocked on nested interactive elements](#interactive-child-elements-within-a-draggable-). Proper semantics for accessibility are added to the _drag handle_ element. If you wish to use an interactive element, `disableInteractiveElementBlocking` must be set. ```js import { Draggable } from 'react-beautiful-dnd'; {(provided, snapshot) => (

My draggable

)}
; ``` ## Draggable Props ```js import type { Node } from 'react'; type Props = {| // required draggableId: DraggableId, index: number, children: DraggableChildrenFn, // optional isDragDisabled: ?boolean, disableInteractiveElementBlocking: ?boolean, shouldRespectForcePress: ?boolean, |}; ``` ### Required props > `react-beautiful-dnd` will throw an error if a required prop is not provided - `draggableId`: A _required_ `DraggableId(string)`. See our [identifiers guide](/docs/guides/identifiers.md) for more information. - `index`: A _required_ `number` that matches the order of the `` in the ``. It is simply the index of the `` in the list. `index` rule: - Must be unique within a `` (no duplicates) - Must be consecutive. `[0, 1, 2]` and not `[1, 2, 8]` Indexes do not need to start from `0` (this is often the case in [virtual lists](/docs/patterns/virtual-lists.md)). In development mode we will log warnings to the `console` if any of these rules are violated. See [Setup problem detection and error recovery](/docs/guides/setup-problem-detection-and-error-recovery.md) Typically the `index` value will simply be the `index` provided by a `Array.prototype.map` function: ```js { this.props.items.map((item, index) => ( {(provided, snapshot) => (
{item.content}
)}
)); } ``` ### Optional props - `isDragDisabled`: A flag to control whether or not the `` is permitted to drag. You can use this to implement your own conditional drag logic. It will default to `false`. - `disableInteractiveElementBlocking`: A flag to opt out of blocking a drag from interactive elements. For more information refer to the section _Interactive child elements within a ``_ - `shouldRespectForcePress`: Whether or not the _drag handle_ should respect force press interactions. See [Force press](#force-press). ## Children function (render props / function as child) The `React` children of a `` must be a function that returns a `ReactNode`. ```js {(provided, snapshot) => (
Drag me!
)}
``` ```js type DraggableChildrenFn = ( DraggableProvided, DraggableStateSnapshot, DraggableRubric, ) => Node; ``` The function is provided with three arguments: ### 1. provided: (DraggableProvided) ```js type DraggableProvided = {| innerRef: (HTMLElement) => void, draggableProps: DraggableProps, // will be null if the draggable is disabled dragHandleProps: ?DragHandleProps, |}; ``` > For more type information please see [our types guide](/docs/guides/types.md). Everything within the _provided_ object must be applied for the `` to function correctly. - `provided.innerRef (innerRef: (HTMLElement) => void)`: In order for the `` to function correctly, **you must** bind the `innerRef` function to the `ReactElement` that you want to be considered the `` node. We do this in order to avoid needing to use `ReactDOM` to look up your DOM node. > For more information on using `innerRef` see our [using `innerRef` guide](/docs/guides/using-inner-ref.md) #### `innerRef` Example ```js {(provided, snapshot) =>
Drag me!
}
// Note: this will not work directly as we are not applying draggableProps or dragHandleProps ``` - `provided.draggableProps (DraggableProps)`: This is an Object that contains a `data` attribute and an inline `style`. This Object needs to be applied to the same node that you apply `provided.innerRef` to. This controls the movement of the draggable when it is dragging and not dragging. You are welcome to add your own styles to `DraggableProps.style` โ€“ but please do not remove or replace any of the properties. #### `draggableProps` type information ```js // Props that can be spread onto the element directly export type DraggableProps = {| // inline style style: ?DraggableStyle, // used for shared global styles 'data-rbd-draggable-context-id': string, 'data-rbd-draggable-id': string, // used to know when a transition ends onTransitionEnd: ?(event: TransitionEvent) => void, |}; ``` > For more type information please see [our types guide](/docs/guides/types.md). #### `draggableProps` Example ```js {(provided, snapshot) => (
Drag me!
)}
// Note: this will not work directly as we are not applying dragHandleProps ``` #### `key`s for a list of `` If you are rendering a list of ``s then it is important that you add a `key` prop to each ``. ```js return items.map((item, index) => ( {(provided, snapshot) => (
{item.content}
)}
)); ``` Rules: - Your `key` needs to be unique within the list - Your `key` should not include the `index` of the item Usually you will want to just use the `draggableId` as the `key` `React` will warn you if your list is missing `keys`. It will not warn you if you are using `index` as a part of your `key`. Not using `keys` correctly will cause really bad times ๐Ÿ’ฅ [`React` docs about `keys`](https://reactjs.org/docs/lists-and-keys.html) #### Positioning ownership It is a contract of this library that it owns the positioning logic of the dragging element. This includes properties such as `top`, `right`, `bottom`, `left` and `transform`. The library may change how it positions things and which properties it uses without performing a major version bump. It is also recommended that you do not apply your own `transition` property to the dragging element. #### Warning: `position: fixed` `react-beautiful-dnd` uses `position: fixed` to position the dragging element. This is quite robust and allows for you to have `position: relative | absolute | fixed` parents. However, unfortunately `position:fixed` is [impacted by `transform`](http://meyerweb.com/eric/thoughts/2011/09/12/un-fixing-fixed-elements-with-css-transforms/) (such as `transform: rotate(10deg);`). This means that if you have a `transform: *` on one of the parents of a `` then the positioning logic will be incorrect while dragging. Lame! For most consumers this will not be an issue. To get around this you can [reparent your ](/docs/guides/reparenting.md). We do not enable this functionality by default as it has performance problems. #### Force press > Safari only In Safari, it is possible for a user to perform a force press action. This is possible with a touch device (`touchforcechange`) and with a mouse (`webkitmouseforcechanged`). We have found that in order to give the most consistent drag and drop experience we need to _opt out_ of force press interactions on a _drag handle_. However, it is possible to have `react-beautiful-dnd` work while also respecting force press interactions. The trade off is that if we register a force press interaction a drag will be cancelled. In order to control this behaviour you set the `shouldRespectForcePress` prop on a ``. By default we set this value to `false` to prevent heavy presses from cancelling a drag. ##### Enabling `shouldRespectForcePress` If you set `shouldRespectForcePress` to `true` then the following will occur: ###### Touch dragging 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. ###### Mouse dragging Any force press action will cancel an existing or pending drag #### Focus retention See [our focus guide](/docs/guides/browser-focus.md) #### Extending `DraggableProps.style` If you are using inline styles you are welcome to extend the `DraggableProps.style` object. You are also welcome to apply the `DraggableProps.style` object using inline styles and use your own styling solution for the component itself. You can use anything you like to style the `` such as - css-in-js such as [`styled-components`](https://www.styled-components.com) or [`emotion`](https://emotion.sh) - sass, less - vanilla css If you are overriding inline styles be sure to do it after you spread the `provided.draggableProps` or the spread will override your inline style. ```js {(provided, snapshot) => { // extending the DraggableStyle with our own inline styles const style = { ...provided.draggableProps.style, backgroundColor: snapshot.isDragging ? 'blue' : 'white', fontSize: 18, }; return (
Drag me!
); }}
``` #### Unsupported `margin` setups Avoid margin collapsing between ``s. [margin collapsing](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing) is one of those really hard parts of CSS. For our purposes, if you have one `` with a `margin-bottom: 10px` and the next `` has a `margin-top: 12px` these margins will _collapse_ and the resulting space between the elements will be the greater of the two: `12px`. When we do our calculations we are currently not accounting for margin collapsing. If you do want to have a margin on the siblings, wrap them both in a `div` and apply the margin to the inner `div` so they are not direct siblings. #### ``s should be visible siblings It is an assumption that ``s are _visible siblings_ of one another. There can be other elements in between, but these elements should not take up any additional space. You probably will not do this anyway, but just calling it out to be super clear. ```js // Direct siblings โœ… {() => {}} {() => {}} // Not direct siblings, but are visible siblings โœ…
{() => {}}
{() => {}}
// Spacer elements โŒ {() => {}}

I will break things!

{() => {}} // Spacing on non sibling wrappers โŒ
{() => {}}
{() => {}}
``` - `provided.dragHandleProps (?DragHandleProps)` every `` has a _drag handle_. This is what is used to drag the whole ``. Often this will be the same node as the ``, but sometimes it can be a child of the ``. `DragHandleProps` need to be applied to the node that you want to be the drag handle. This is a number of props that need to be applied to the `` node. The simplest approach is to spread the props onto the draggable node (`{...provided.dragHandleProps}`). However, you are also welcome to [monkey patch](https://davidwalsh.name/monkey-patching) these props if you also need to respond to them. DragHandleProps will be `null` when `isDragDisabled` is set to `true`. #### `dragHandleProps` Type information ```js type DragHandleProps = {| // what draggable the handle belongs to 'data-rbd-drag-handle-draggable-id': DraggableId, // What DragDropContext the drag handle is in 'data-rbd-drag-handle-context-id': ContextId, // Id of hidden element that contains the lift instruction (nicer screen reader text) 'aria-labelledby': ElementId, // Allow tabbing to this element tabIndex: number, // Stop html5 drag and drop draggable: boolean, onDragStart: (event: DragEvent) => void, |}; ``` #### `dragHandleProps` Example: standard ```js {(provided, snapshot) => (
Drag me!
)}
``` #### `dragHandleProps` example: custom drag handle Controlling a whole draggable by just a part of it ```js {(provided, snapshot) => (

Hello there

Drag handle
)}
``` ### 2. Snapshot: (DraggableStateSnapshot) ```js type DraggableStateSnapshot = {| // Set to true if a Draggable is being actively dragged, or if it is drop animating // Both active dragging and the drop animation are considered part of the drag // *Generally this is the only property you will be using* isDragging: boolean, // Set to true if a Draggable is drop animating. Not every drag and drop interaction // as a drop animation. There is no drop animation when a Draggable is already in its final // position when dropped. This is commonly the case when dragging with a keyboard isDropAnimating: boolean, // Information about a drop animation dropAnimation: ?DropAnimation // What Droppable (if any) the Draggable is currently over draggingOver: ?DroppableId, // the id of a draggable that you are combining with combineWith: ?DraggableId, // if something else is dragging and you are a combine target, then this is the id of the item that is dragging combineTargetFor: ?DraggableId, // There are two modes that a drag can be in // 'FLUID': everything is done in response to highly granular input (eg mouse) // 'SNAP': items snap between positions (eg keyboard); mode: ?MovementMode, |}; ``` > See our [type guide](/docs/guides/types.md) for more details The `children` function is also provided with a small amount of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `` while it is being dragged. Note: if you want to change the cursor to something like `grab` you will need to add the style to the draggable. (See [Extending `DraggableProps.style`](#extending-draggableprops-style) above) ```js {(provided, snapshot) => { const style = { backgroundColor: snapshot.isDragging ? 'blue' : 'grey', ...provided.draggableProps.style, }; return (
Drag me!
); }}
``` ### 3. rubric: (DraggableRubric) ```js type DraggableRubric = {| draggableId: DraggableId, type: TypeId, source: DraggableLocation, |}; ``` `rubric` represents all of the information associated with a ``. `rubric` is helpful for looking up the data associated with your `` when it is not available in the current scope. This is useful when using the ` | renderClone` API. The `rubric` is the same lookup information that is provided to the [`Responder`s](/docs/guides/responders.md). ## Adding an `onClick` handler to a `` or a _drag handle_ You are welcome to add your own `onClick` handler to a `` or a _drag handle_ (which might be the same element). `onClick` events handlers will always be called if a click occurred. If we are preventing the click, then the `event.defaultPrevented` property will be set to `true`. We prevent click events from occurring when the user was dragging an item. See [sloppy clicks and click prevention](/docs/sensors/mouse.md#sloppy-clicks-and-click-prevention-) for more information. ## Interactive child elements within a `` It is possible for your `` to contain interactive elements. By default we block dragging on these elements. By doing this we allow those elements to function in the usual way. Here is the list of interactive elements that we block dragging from by default: - `input` - `button` - `textarea` - `select` - `option` - `optgroup` - `video` - `audio` - [`contenteditable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable) (any elements that are `contenteditable` or are within a `contenteditable` container) You can opt out of this behavior by adding the `disableInteractiveElementBlocking` prop to a ``. However, it is questionable as to whether you should be doing so because it will render the interactive element unusable. If you need to _conditionally_ block dragging from interactive elements you can add the `disableInteractiveElementBlocking` prop to opt out of the default blocking and monkey patch the `dragHandleProps (DragHandleProps)` event handlers to disable dragging as required. [โ† Back to documentation](/README.md#documentation-) --- # `` `` components can be **dropped on by a ``**. They also **contain** ``s. A `` must be contained within a ``. ```js import { Droppable } from 'react-beautiful-dnd'; {(provided, snapshot) => (

I am a droppable!

{provided.placeholder}
)}
; ``` ## Droppable props ```js import type { Node } from 'react'; type Props = {| // required droppableId: DroppableId, // optional type?: TypeId, mode?: DroppableMode, isDropDisabled?: boolean, isCombineEnabled?: boolean, direction?: Direction, ignoreContainerClipping?: boolean, renderClone?: DraggableChildrenFn, getContainerForClone?: () => HTMLElement, children: (DroppableProvided, DroppableStateSnapshot) => Node, |}; type DroppableMode = 'standard' | 'virtual'; type Direction = 'horizontal' | 'vertical'; ``` ### Required props > `react-beautiful-dnd` will throw an error if a required prop is not provided - `droppableId`: A _required_ `DroppableId(string)`. See our [identifiers guide](/docs/guides/identifiers.md) for more information. ### Optional props - `type`: A `TypeId(string)` that can be used to simply accept only the specified class of ``. ``s always inherit type from the `` they are defined in. For example, if you use the type `PERSON` then it will only allow ``s of type `PERSON` to be dropped on itself. ``s of type `TASK` would not be able to be dropped on a `` with type `PERSON`. If no `type` is provided, it will be set to `'DEFAULT'`. - `isDropDisabled`: A flag to control whether or not dropping is currently allowed on the ``. You can use this to implement your own conditional dropping logic. It will default to `false`. - `isCombineEnabled`: A flag to control whether or not _all_ the `Draggables` in the list will be able to be **combined** with. It will default to `false`. - `direction`: The direction in which items flow in this droppable. Options are `vertical` (default) and `horizontal`. - `ignoreContainerClipping`: When a `` is inside a scrollable container its area is constrained so that you can only drop on the part of the `` that you can see. Setting this prop opts out of this behavior, allowing you to drop anywhere on a `` even if it's visually hidden by a scrollable parent. The default behavior is suitable for most cases so odds are you'll never need to use this prop, but it can be useful if you've got very long ``s inside a short scroll container. Keep in mind that it might cause some unexpected behavior if you have multiple ``s inside scroll containers on the same page. - `mode`: `standard` (default) or `virtual`. Used to designate a list as a virtual list. See our [virtual lists pattern](/docs/patterns/virtual-lists.md) - `renderClone`: used to render a clone (replacement) of the dragging `` while a drag is occurring. See our [reparenting guide](/docs/guides/reparenting.md) for usage details. **A clone must be used for [virtual lists](/docs/patterns/virtual-lists.md).** You can use a clone without using virtual lists - `getContainerForClone`: a function that returns the containing element (parent element) for a clone during a drag. See our [reparenting guide](/docs/guides/reparenting.md). ## Children function The `React` children of a `` must be a function that returns a [`ReactElement`](https://tylermcginnis.com/react-elements-vs-react-components/). ```js {(provided, snapshot) => ({ /*...*/ })} ``` The function is provided with two arguments: ### 1. provided: (DroppableProvided) ```js import type { Node } from 'react'; type DroppableProvided = {| innerRef: (?HTMLElement) => void, droppableProps: DroppableProps, placeholder: ?Node, |}; type DroppableProps = {| // used for shared global styles 'data-rbd-droppable-context-id': ContextId, // Used to lookup. Currently not used for drag and drop lifecycle 'data-rbd-droppable-id': DroppableId, |}; ``` - `provided.innerRef`: In order for the droppable to function correctly, **you must** bind the `provided.innerRef` to the highest possible DOM node in the `ReactElement`. We do this in order to avoid needing to use `ReactDOM` to look up your DOM node. > For more information on using `innerRef` see our [using `innerRef` guide](/docs/guides/using-inner-ref.md) - `provided.placeholder`: This is used to create space in the `` as needed during a drag. This space is needed when a user is dragging over a list that is not the home list. Please be sure to put the placeholder inside of the component for which you have provided the ref. We need to increase the size of the `` itself. - `provided.droppableProps (DroppableProps)`: This is an Object that contains properties that need to be applied to a Droppable element. It needs to be applied to the same element that you apply `provided.innerRef` to. It currently contains `data` attributes that we use for styling and lookups. ```js {(provided, snapshot) => (
Good to go {provided.placeholder}
)}
``` ### 2. snapshot: (DroppableStateSnapshot) ```js type DroppableStateSnapshot = {| // Is the Droppable being dragged over? isDraggingOver: boolean, // What is the id of the draggable that is dragging over the Droppable? draggingOverWith: ?DraggableId, // What is the id of the draggable that is dragging from this list? // Useful for styling the home list when not being dragged over draggingFromThisWith: ?DraggableId, // Whether or not the placeholder is actively being used. // This is useful information when working with virtual lists // (See our virtual list pattern) isUsingPlaceholder: boolean, |}; ``` The `children` function is also provided with a small amount of state relating to the current drag state. This can be optionally used to enhance your component. A common use case is changing the appearance of a `` while it is being dragged over. ```js {(provided, snapshot) => (
I am a droppable! {provided.placeholder}
)}
``` ## Combining `react-beautiful-dnd` supports the combining of ``s ๐Ÿคฉ ![combining](https://user-images.githubusercontent.com/2182637/48045145-318dc300-e1e3-11e8-83bd-22c9bd44c442.gif) You can enable a _combining_ mode for a `` by setting `isCombineEnabled` to `true` on a ``. We have created a [combining guide](/docs/guides/combining.md) to help you implement combining in your lists. ## Adding and removing ``s while dragging It is possible to change the ``s in a `` for a limited set of circumstances. We have created a comprehensive [changes while dragging guide](/docs/guides/changes-while-dragging.md) ## Conditionally dropping - ``s can only be dropped on by ``s who share the same `type`. This is a simple way of allowing conditional dropping. If you do not provide a `type` for the ``, then it will only accept ``s which also have the default type. ``s and ``s both will have their `types` set to `'DEFAULT'` when none is provided. There is currently no way to set multiple `types`, or a `type` wildcard that will accept ``s of multiple any types. This could be added if there is a valid use case. - Using the `isDropDisabled` prop you can conditionally allow dropping. This allows you to do arbitrarily complex conditional transitions. This will only be considered if the `type` of the `` matches the `type` of the currently dragging ``. - You can disable dropping on a `` altogether by always setting `isDropDisabled` to `true`. You can do this to create a list that is never able to be dropped on, but contains ``s. - Technically you do not need to use `type` and do all of your conditional drop logic with the `isDropDisabled` function. The `type` parameter is a convenient shortcut for a common use case. ## Scroll containers This library supports dragging within scroll containers (DOM elements that have `overflow: auto;` or `overflow: scroll;`). The **only** supported use cases are: 1. The `` can itself be a scroll container with **no scrollable parents** 2. The `` has **one scrollable parent** where a _scrollable parent_ refers to a scroll container that is not the window itself. For more information see [how we detect scroll containers guide](/docs/guides/how-we-detect-scroll-containers.md) > We currently only support a single scroll parent. We plan on adding support for [nested scroll containers](https://github.com/atlassian/react-beautiful-dnd/issues/131) ## Empty ``s It is recommended that you put a `min-height` on a vertical `` or a `min-width` on a horizontal ``. Otherwise when the `` is empty there may not be enough of a target for `` being dragged with touch or mouse inputs to be _over_ the ``. ## Fixed ``s `react-beautiful-dnd` has partial support for `` lists that use `position: fixed`. When you start a drag and _any_ list of the same type is `position:fixed` then auto window scrolling will be disabled. This is because our virtual model assumes that when the page scroll changes the position of a `` will shift too. If a manual window scroll is detected then the scroll will be aborted. Scroll container scroll is still allowed. We could improve this support, but it would just be a big effort. Please raise an issue if you would be keen to be a part of this effort โค๏ธ ## Recommended ๐Ÿ  home list styling We recommend you style the home list when it is not being dragged over. This makes it easy for a user to see where an item is dragging from. You can use the `snapshot.draggingFromThisWith` value for this. This will be populated in the home list. 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](https://user-images.githubusercontent.com/2182637/54155390-251ebd00-4498-11e9-8748-ab441795d19f.gif) ```js const getBackgroundColor = (snapshot: DroppableStateSnapshot): string => { // Giving isDraggingOver preference if (snapshot.isDraggingOver) { return 'pink'; } // If it is the home list but not dragging over if (snapshot.draggingFromThisWith) { return 'blue'; } // Otherwise use our default background return 'white'; }; ``` ## Recommended `` performance optimisation > ๐Ÿ“บ This optimisation is covered in a [free lesson of our getting started course](https://egghead.io/lessons/react-optimize-performance-in-react-beautiful-dnd-with-shouldcomponentupdate-and-purecomponent) When a user drags over, or stops dragging over, a `` we re-render the `` with an updated `DroppableStateSnapshot > isDraggingOver` value. This is useful for styling the ``. However, by default this will cause a render of all of the children of the `` - which might be 100's of ``s! This can result in a noticeable frame rate drop. To avoid this problem we recommend that you create a component that is the child of a `` whose responsibility it is to avoid rendering children if it is not required. Here is an example of how you could do this using `class` components: ```js import React, { Component } from 'react'; class Student extends Component<{ student: Person }> { render() { // Renders out a draggable student } } class InnerList extends Component<{ students: Person[] }> { // do not re-render if the students list has not changed shouldComponentUpdate(nextProps: Props) { if (this.props.students === nextProps.students) { return false; } return true; } // You could also not do your own shouldComponentUpdate check and just // extend from React.PureComponent render() { return this.props.students.map((student: Person) => ( )); } } class Students extends Component<{ students: Person[] }> { render() { return ( {(provided: DroppableProvided, snapshot: DroppableStateSnapshot) => (
{provided.placeholder}
)}
); } } ``` Here is an example of how you could do this using `function` components: ```js import React from 'react'; function Student (props: { student: Person }) { // Renders out a draggable student } // do not re-render if the students list reference has not changed const InnerList = React.memo(function InnerList(props: students: Person[]) { return props.students.map((student: Person) => ( )); }); function Students(props: { students: Person[] }) { return ( {(provided: DroppableProvided, snapshot: DroppableStateSnapshot) => (
{/* only re-render if the students array reference changes */} {provided.placeholder}
)}
); } ``` By using the approach you are able to make style changes to a `` when it is being dragged over, but you avoid re-rendering all of the children unnecessarily. When moving into a new list, the visible `Draggables` will have their `render` function called directly even with this optimisation. This is because we need to move those `Draggables` out of the way. The `InnerList` optimisation will prevent the `` from calling `render` on the whole list from the top down. This optimisation will prevent the non-visible `Draggables` from having their render function called. Unfortunately we are [unable to apply this optimisation for you](https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9). It is a byproduct of using the render-props pattern. [โ† Back to documentation](/README.md#documentation-) --- # `resetServerContext` The `resetServerContext` function should be used when server side rendering (SSR). It ensures context state does not persist across multiple renders on the server which would result in client/server markup mismatches after multiple requests are rendered on the server. Use it before calling the server side render method: ```js import { resetServerContext } from 'react-beautiful-dnd'; import { renderToString } from 'react-dom/server'; // ... resetServerContext(); renderToString(...); ``` [โ† Back to documentation](/README.md#documentation-) --- # Auto scrolling When a user drags a `` near the edge of a _container_ we automatically scroll the container as we are able to in order make room for the ``. > A _container_ is either a `` that is scrollable or has a scroll parent - or the `window`. | Mouse and touch | Keyboard | | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | ![auto-scroll-mouse](https://user-images.githubusercontent.com/2182637/36520373-c9e2cb7e-17e4-11e8-9e93-4d2389d51fa4.gif) | ![auto-scroll-keyboard](https://user-images.githubusercontent.com/2182637/36520375-cc1aa45c-17e4-11e8-842d-94aed694428a.gif) | It also works in multi list configurations with all input types | Mouse and touch | Keyboard | | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | ![auto-scroll-board-mouse](https://user-images.githubusercontent.com/2182637/36520670-57752526-17e6-11e8-95b3-b5a3978a5312.gif) | ![auto-scroll-board-keyboard](https://user-images.githubusercontent.com/2182637/36520650-3d3638f8-17e6-11e8-9cba-1fb439070285.gif) | ## For mouse and touch inputs ๐Ÿญ๐Ÿ“ฑ When the center of a `` 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 `` manually using their _mouse wheel_ or _trackpad_ ๐Ÿ‘Œ ### A note about big ``s If the `` 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 `` 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 `` 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 `` into the correct position we can do a combination of a `` scroll, `window` scroll and manual movements to ensure the `` 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. [โ† Back to documentation](/README.md#documentation-) --- # Avoiding image flickering > Often all you need to do is close your browsers dev tools! See 'HTTP cache headers below' If your `` has a image inside of it, then you might notice that sometimes it flashes sometimes. Why is that? Some behaviours will cause a `` to be **recreated**. This is where the original DOM element is destroyed, and a new DOM element is created. When the new DOM element is inserted into the DOM then the browser will try to load the image from scratch. Image flashing is caused by the gap between the new element being inserted into the DOM and the image being loaded. These are the actions that can cause a `` to be recreated: - [Reparenting](/docs/guides/reparenting.md) a `` (using the cloning api, or using your own portal) - Moving `` into a new list. React will not shift the original element. It will recreate one. ## How can you prevent image flickering? The big idea is you want to allow the browser to load the image **instantly** when it is recreated. Here are some ways you can do that: ### HTTP cache headers > When you open devtools, it can disable HTTP caching. So simply closing devtools might make your image flickering go away! ๐Ÿค˜ Generally speaking, a browser will not request an image that it already has cached and it will load instantly. You can use the [HTTP cache headers](https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers) to tell a browser that an image can be cached. Ultimately the browser can decide to re-request the image if it wants to, but that would be an edge case. We put together an [example on Glitch](https://glitch.com/~image-flickering) that shows off the impact of using HTTP cache headers. ### Inline your images [Base64 encode](https://stackoverflow.com/questions/201479/what-is-base-64-encoding-used-for) your images and use that as the source. That way there is no need to talk to the server to get the source. ```diff - + ``` You can use the [webpack `url-loader`](https://github.com/webpack-contrib/url-loader) to help. #### Drawbacks of this approach - If the same image is used in multiple places, they all need to be downloaded independently - The browser cannot defer image loading You will want to keep your image sizes fairly small. ### Really anything else! The big idea is that you don't want to be calling the server to refetch an image that has already been fetched. So anything you can use to do client side caching of images is fine. You could even use [service workers](https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker) if you want! [โ† Back to documentation](/README.md#documentation-) --- # Browser focus > "You got to focus on what's real, man" - [Jake from Adventure time](https://www.youtube.com/watch?v=TFGz6Qvg1CE) `react-beautiful-dnd` includes logic to maintain browser focus for _drag handles_. This especially important for [keyboard dragging](/docs/sensors/keyboard.md) which requires the dragging item to be focused. ## Terminology reminder ๐Ÿ“– A `` has a _drag handle_. A _drag handle_ is the part of the `` that controls the dragging of the whole ``. A _drag handle_ can be the same element as the `` ## Drag handle not focused at drag start If the _drag handle_ is not focused when a drag starts then **focus is not given** to the dragging item. This is a mirror of the native HTML5 drag and drop behaviour which does not give focus to an item just because it is dragging. You are welcome to call `HTMLElement.focus()` when a drag starts to give it focus, but that is up to you. ## Drag handle is focused at drag start If a _drag handle_ has browser focus when a drag starts then `rbd` will try to give focus to the _drag handle_ during a drag and just after a drag ends. Here is what is done: - Give focus to a _drag handle_ with a matching `DraggableId` after the drag starts. This might be a different element to the original _drag handle_ if you are [reparenting your ``](/docs/guides/reparenting.md). - Give focus to a _drag handle_ with a matching `DraggableId` after the drag ends. Sometimes the original _drag handle_ element is lost during a drag, such as when [reparenting your ``](/docs/guides/reparenting.md), or when moving a `` from one list to another as `React` will recreate the element. - If [combining](/docs/guides/combining.md) then focus is given to the combine target after a drag ends. This allows keyboard users to continue to engage with the application without needing to get the focus back to where they where the last interaction was ## Browser testing Fun fact: we test this behaviour using [`cypress.io`](http://cypress.io) to ensure that focus management behaves as we expect [โ† Back to documentation](/README.md#documentation-) --- # Changes while dragging > For virtual list support see our [virtual list pattern](/docs/patterns/virtual-lists.md) > โŒ **This behaviour is only supported in `11.x`**. We do plan on supporting this type of behaviour again in a future `minor` release. We needed to cut this existing behaviour order to get `12.x` across the line. Going forward, tree behaviour will be supported on the latest version. We know this sucks, but we thought it better to move things forward. `react-beautiful-dnd` supports the addition and removal of ``s during a drag. ## What behaviours does this unlock? ### Lazy loading of list items > In this example we are adding more ``s to a list we scroll closer to the bottom of the list ![lazy-loading 2018-11-01 17_01_21](https://user-images.githubusercontent.com/2182637/47835395-ec8b1a80-ddf7-11e8-88e6-848848ab4af1.gif) ### Collapsing and expanding groups > We recommend you use the [`@atlaskit/tree`](https://atlaskit.atlassian.com/packages/core/tree) component for this behaviour ![hover_to_expand](https://user-images.githubusercontent.com/2182637/45996092-3d637100-c0de-11e8-8837-8d66e7cc73b8.gif) ## Rules > We attempt to print helpful debug information to the `console` if you do not follow these rules in development builds - You are allowed to add or remove `Draggables` during a drag - You can only add or remove `Draggables` that are of the same `type` as the dragging item. - Any changes must occur within a `` that is a _scroll container_ (has `overflow: auto` or `overflow: scroll`). _This is prevent accidental shifts to other `Droppables` on the page_ - The size of the internal content of the _scroll container_ can change, but the outer bounds of the _scroll container_ itself cannot change. - You cannot modify the sizes of any existing `` or `` during a drag - You cannot add or remove a `` during a drag. _We did this to avoid accidental shifting of other ``s_ - When an item is removed or added it must be done instantly. You cannot animate the size of the item. You are welcome to animate a property when adding a `` that does not impact the size of the item, such as `opacity` ## ` > onDragUpdate` behavior - `onDragUpdate` will be called if the `DragUpdate > source > index` of the dragging item has changed as the result of `Draggables` being added or removed before it. - `onDragUpdate` will be called if the `DragUpdate > destination` of the dragging item has changed as a result of the addition or removal. ## ` > onDragEnd` behavior `onDragEnd` will be called with values that are adjusted for any additions or removals of `Draggables` during a drag. This can mean that the `onDragStart: DragStart > source > index` can be different from the `onDragEnd: DropResult > source > index`. ### Sample `onDragEnd` flow > What is important to note is that the `source` property can change during a drag as a result of dynamic changes. 1. A drag starts. `onDragStart` is called with: ```js { draggableId: 'item-1',, type: 'TYPE', source: { droppableId: 'droppable', index: 1, }, } ``` 2. The first `` in the list (`item-0`) is removed. `onDragUpdate` is called with `DragUpdate`: ```diff { draggableId: 'item-1',, type: 'TYPE', source: { droppableId: 'droppable', + // item-1 is now in index 0 as item-0 is gone + index: 0, }, // adjusted destination destination: null, } ``` 3. The drag ends `onDragEnd` is called with `DropResult`: ```diff { draggableId: 'item-1',, type: 'TYPE', source: { droppableId: 'droppable', + // the source reflects the change + index: 0, }, destination: null, reason: 'DROP', } ``` ## Drag end while we are patching the virtual model If a drag ends after a `` has been added or removed, but we have not finished collecting and patching the _virtual dimension model_ then we will delay the drop until the patch is finished. This is usually only a single frame. The `onDropEnd` callback will be called with a `DropResult` that is correct after the patch. [โ† Back to documentation](/README.md#documentation-) --- # Combining > ๐Ÿ‘ถ This feature is still quite young. We wanted to get it out there for people to play with `react-beautiful-dnd` supports the combining of ``s ๐Ÿคฉ ![combining](https://user-images.githubusercontent.com/2182637/48045145-318dc300-e1e3-11e8-83bd-22c9bd44c442.gif) > ๐ŸŒฒ If you are looking to build a tree view, we have built one already! [@atlaskit/tree](https://atlaskit.atlassian.com/packages/confluence/tree) ## Setup In order to enable combining you need to set `isCombineEnabled` to `true` on a `` and you are good to go! ```js ... ``` ## Behaviour When `isCombineEnabled` is set on a list _any_ item in the list can be combine with. You can toggle `isCombineEnabled` during a drag. `react-beautiful-dnd` works hard to ensure that users are able to combine and reorder within the same list in a way that feels intuitive and natural. ## Current limitations - No granular control over which items can be combined with within the list. We could move to the `isCombineEnabled` prop from a `` to a `` to allow this sort of customisation. However, in order to ship this huge feature we went a bit simplier to start with - A list must be reorderable to also have items that can be combined with. It is not possible for a list to be 'combine only' at this stage ## `` > `DraggableStateSnapshot` ```diff type DraggableStateSnapshot = {| isDragging: boolean, isDropAnimating: boolean, dropAnimation: ?DropAnimation, draggingOver: ?DroppableId, + combineWith: ?DraggableId, + combineTargetFor: ?DraggableId, mode: ?MovementMode, |}; ``` If you are dragging a `` over another `` in combine mode then the id of the `` being dragged over will be populated in `combineWith` If a `` is being dragged over in combine mode then the id of the `` being dragged will be populated in `combineTargetFor` ## `` > `Responders` `onDragUpdate` and `onDragEnd` will be updated with any changes to a `combine` > See our [type guide](/docs/guides/types.md) for more details ## Persisting a `combine` A `combine` result might signify different operations depending on your problem domain. When combining, a simple operation is to just remove the item that was dragging ```js function onDragEnd(result) { // combining item if (result.combine) { // super simple: just removing the dragging item const items: Quote[] = [...this.state.items]; items.splice(result.source.index, 1); setState({ items }); return; } } ``` ## Drop animation One of the goals of `react-beautiful-dnd` is to create a drag and drop experience that feels physical. This is a bit tricky to achieve in a generic way when it comes to combining two things. What we have gone for out of the box in the following animation: - move the dragging item onto the center of the item being grouped with - fade the opacity of the dragging item down to `0` - scale the dragging item down This animation attempts to communicate one item _moving into_ another item in a fairly generic way. ![combining](https://user-images.githubusercontent.com/2182637/48045145-318dc300-e1e3-11e8-83bd-22c9bd44c442.gif) You are welcome to customise this animation using the information found in our [drop animation guide](/docs/guides/drop-animation.md) [โ† Back to documentation](/README.md#documentation-) --- # Common setup issues This is a little guide to help you with some common setup issues ## Check your `console` For detectable setup issues we try to log information in the `console` for `development` builds of `react-beautiful-dnd`. If things are not working, first thing to do is check your `console`. ## React version Please ensure that you meet our peer dependency version of `React`. Your React version needs to be greater than or equal to `16.8.5`. If you want to know what React version you are on take a look at your [`package.json`](https://docs.npmjs.com/files/package.json) or use `console.log(React.version)`. If you are not sure if your `package.json` version satisfies `16.8.5` have a read of [npm: about semantic versioning](https://docs.npmjs.com/about-semantic-versioning) and try out the [npm sermver calculator](https://semver.npmjs.com/) ## No duplicate ids `draggableId` and `droppableId` values must be unique for the whole `` and not just a list. More information: [identifiers guide](/docs/guides/identifiers.md) ## `` indexes Rules: - Must be unique within a `` (no duplicates) - Must be consecutive. `[0, 1, 2]` and not `[1, 2, 8]` Indexes do not need to start from `0` (this is often the case in [virtual lists](/docs/patterns/virtual-lists.md)) [More information](/docs/api/draggable.md#draggable-props) ## No margin collapsing between ``s This can happen if you have a `margin-top` as well as a `margin-bottom` on a ``. [More information](/docs/api/draggable.md#unsupported-margin-setups) ## `key`s for a list of `` If you are rendering a list of ``s then it is important that you add a [`key`](https://reactjs.org/docs/lists-and-keys.html) prop to each ``. ```js return items.map((item, index) => ( {(provided, snapshot) => (
{item.content}
)}
)); ``` [More information](/docs/api/draggable.md) ## Avoid empty lists We recommend you set a `min-height` or `min-width` on a `` to ensure that there is a visible drop target when a list is empty We go over this in our [Get started with `react-beautiful-dnd` course](https://egghead.io/lessons/react-move-items-between-columns-with-react-beautiful-dnd-using-ondragend) ## Image flickering in a `` See our [avoiding image flickering guide](/docs/guides/avoiding-image-flickering.md) [โ† Back to documentation](/README.md#documentation-) --- # Content Security Policy > This page is to help you get around the CSP error: "Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'"." > A huge thankyou to [@Zweder](https://github.com/Zweder) for driving this effort Content Security Policy (CSP) is a way of controlling where a browser can download assets from, as well as what those assets are allowed to do. Background reading on CSP - [Google guide](https://developer.chrome.com/extensions/contentSecurityPolicy) - [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) - [Helmetjs guide](https://helmetjs.github.io/docs/csp/) `react-beautiful-dnd` creates a `