Drag gestures are becoming increasingly more popular in Web UIs – and for good reason! They’re super easy to use!
They extend the fluid “life-like” experience we’ve become accustomed to from the mobile/tablet world. Therefore, it’s important that this library includes a solid and flexible drag / drop / sort system.
The funny thing is… Drag/Sort systems are almost always excluded from Component libraries. The main reason is… well… because they’re heavy and complicated (aka. really hard!). I believe taking on this complexity is worth it as we’ll be able to provide users with an easy to use + powerful way to create highly interactive experiences – be that in Gutenberg’s UI, custom Block controls, WP Admin, and beyond.
An illustration of 4 drag system features: Dropzones, cross-app, sorting, and cross-context. From my research, experience, and experiments, I’ve identified 4 primary features (or use cases) that a draggable system should have:
Dropzones are typically used to as areas (or targets) that allow users to drop files into. For example, dropping a .png image file to upload to a server. The draggable element typically comes from outside the browser, like from a user’s desktop. Dropzones may also accommodate the dragging and dropping of non-file elements from within the app.
Cross-app drag/drop interactions enable users to drag things from the browser and drop them into a separate application. For example, dragging a chunk of content and pasting it into a separate Notes application.
Sorting enables users to drag items (typically within a list/grid) to re-arrange the order of things. The sorting feedback is often communicated with animations that visualize items shifting into their new positions. As an added (and more challenging) bonus, sorting should accommodate nested lists.
Cross-context interactions enable users to drag/drop elements from different “types”. The best example of this would be a Kanban style board (e.g. Trello), where users can drag/drop cards into different columns.
An illustration indicating screen reader, dragless actions, and reduced motion. There are several accessibility concerns the drag system should support (out-of-the-box):
Dragless actions (e.g. clicking or using keyboard only for interactions) Reduced motion Screen Reader Support The drag system should have proper aria descriptions, tab handling, and identifiers. It would be great to support the announcements (for voiceovers) during various lifecycle events during the drag/drop experience.
Users should be able to perform all of the drag interactions without actually having to drag anything. This may mean providing on-screen buttons, allowing for actions to be triggered by mouse clicks. It may also mean having deliberate focus interactions, allowing for keyboard-only interaction.
Users should be able to reduce/disable animations from interactions like drag/sort.
I’ve evaluated a handful of libraries, including:
- React Sortable HOC
- React DND
- React Beautiful DND
The best solution, in my opinion, would be React Beautiful DND, as it accommodates most of the features and a11y concerns outlined above (but not all). My hope is that is is flexible enough to serve as the foundations of an app-wide drag/drop system.
One example I created with React Beautiful DND would be a simple mock “Block Builder”:
A GIF demonstrating cross-context and sortable drag interactions in a mock “block builder”. (Link to the live demo)
It demonstrates how blocks can be dragged into a content area, as well as how content can be re-ordered through drag interactions.
We are still incredibly early in researching and refining a drag system. The research has been helpful in identifying core features and must-have a11y concerns. Beyond this, there’s also a lot of considerations and care we must put into the design of drag experiences as well as component API.
It should feel easy for designers and devs to work with and implement a drag/drop interaction.
It should feel even easier for users to use these experiences.
P.S. Here’s a link to the original Github issue.
Originally posted on the G2 Components project blog.