Drag and Drop
Drag and drop is an intuitive way for users to transfer data between locations. React Aria implements drag and drop for mouse and touch interactions, and provides full keyboard and screen reader accessibility.
Drag and drop is a common UI interaction that allows users to transfer data between two locations by directly moving a visual representation on screen. It is a flexible, efficient, and intuitive way for users to perform a variety of tasks, and is widely supported across both desktop and mobile operating systems. In addition to the standard mouse and touch interactions, React Aria also implements keyboard and screen reader accessible alternatives for drag and drop to enable all users to perform these tasks.
Drag and drop allows a user to move data between two locations. The initial location is referred to as a drag source, and the final location is referred to as a drop target. The source and target may be within the same application, for example two adjacent lists, or in different applications, for example uploading files from the desktop.
The drag source is responsible for providing one or more drag items, which specify the data to be dragged. A drag item may be an object represented by the draggable element, a file, plain text content, etc. Each drag item includes a type, and the actual data for the item. The type of a drag item can be one of the common mime types or a custom type specific to the application. Multiple representations of the same object may be provided in different formats for interoperability with various drop targets. This allows drag and drop to work even between different applications. For example, a drag source may provide the data for a drag in both a custom object format and as plain text. This allows dropping within the application to include richer functionality, but also allows the user to drop in external applications such as email clients or text editors.
While dragging, a drag preview is displayed under the user's mouse or finger to indicate the items being dragged. By default, this is a copy of the dragged element, but it can be customized. For example, when multiple items are dragged, they could be shown as a stack, or with a badge indicating the count.
There are several drop operations that can be performed as a result of a drag and drop interaction:
move– the dragged data is moved from its source location to the target location.
copy– the dragged data is copied to the target destination.
link– a relationship is established between the source and target locations.
cancel– the drag and drop operation is canceled, resulting in no changes made to the source or target.
Many operating systems display drop operations in the form of a cursor change when hovering over a drop target, e.g. a plus sign to indicate a copy operation. The user may also be able to use a modifier key to choose which drop operation to perform, such as Option or Alt to switch from move to copy. The drag source can also specify what drop operations are allowed for its data, allowing the drop target to decide what operation to perform, using the restrictions set by the drag source as a guideline.
Collection components built with hooks such as useListBox, useTable, and useGridList, support multiple drop positions. The collection may support a
"root" drop position, allowing items to be dropped on the collection as a whole. It may also support
"on" drop positions, such as when dropping into a folder in a list. If the collection allows the user to control the order of the items, it may also support
"between" drop positions, allowing the user to insert or move items between other items. This is indicated by rendering a drop indicator between two items when the user drags over the space between them. Any number of these drop positions can be allowed at the same time and the component can use the types of the dragged items to selectively allow or disallow certain positions.
While drag and drop has historically been mostly limited to mouse and touchscreen users, keyboard and screen reader friendly alternatives are important for users who cannot use these interaction methods. For example, copy and paste can often be used as an alternative to drag and drop to allow the user to move an object from one location to another. However, copy and paste does not cover all of the possible interactions that drag and drop allows. For example, it is hard to specify an exact location to insert an item into a list on paste, or even know where pasting is accepted. Users must either already know where they can paste, or navigate aimlessly until they find a valid location.
React Aria implements keyboard and screen reader friendly interactions for drag and drop that provide full parity with the mouse and touch experiences. Users can press Enter on a draggable element to enter drag and drop mode. Then, they can press Tab to cycle between the drop targets that accept the dragged data, then press Enter to drop. Escape can be pressed at any time to cancel. Touch screen reader users can also drag by double tapping to activate drag and drop mode, swiping between drop targets, and double tapping again to drop. Screen reader announcements are included to help guide the user through this process. All of this is built into the useDrag and useDrop hooks.
Collection components such as lists or tables are treated as a single drop target, so that users can easily tab past them to get to the next drop target without going through every item. Instead, within a droppable collection, keys such as ArrowDown and ArrowUp can be used to select a drop position, such as on an item, or between items. The exact interactions may vary depending on the layout of the collection component. Drag and drop for collections is implemented by the useDraggableCollection and useDroppableCollection hooks.
Draggable elements can sometimes have other interactions that conflict with the keyboard and screen reader interactions needed to initiate a drag, such as the Enter key. In these cases, an explicit drag affordance may be added. Keyboard and screen reader users can focus this element, and use it to initiate drag and drop for the parent item. In addition, this has the added benefit of making drag and drop more discoverable.
Note that because mouse and touch drag and drop interactions utilize the native browser APIs, they work both within the browser window and with external applications on the user's device. Keyboard and screen reader drag and drop is implemented from scratch, and therefore can only be supported within the browser window. Alternative interactions for operations involving external applications, such as file uploading, should be implemented in addition to drag and drop to ensure that all users can perform these tasks. One possible way to do this is via copy and paste. See the useClipboard hook for more details.