Summary:
react-beautiful-dnd
does not support the usage of<svg>
(SVGElement
) for a<Draggable />
or it's drag handle. You are still able to drag SVG's around using a number of different strategies listed below
Background: HTMLElement
We require that a <Draggable />
and its drag handle be a HTMLElement
. Almost every element that you make in the browser is a HTMLElement
. See huge list on MDN. A HTMLElement
extends Element
We use and manipulate focus on a drag handle during a drag if it is needed. This is especially true for keyboard dragging that relies on focus management.
An element loses focus when it moves into a React Portal
. We can detect when a <Draggable />
is moving into a portal and we give the new element in the portal focus with .focus()
. Additionally, we also will maintain focus when you move a <Draggable />
from one list to another using .focus()
if it had focus when dragging. An element will always have focus when keyboard dragging.
Enter SVGElement
🖼
An SVGElement
does not implement HTMLElement
, and directly extends Element
.
SVGElement
has inconsistent, and sometimes, non-existent focus management behavior across browsers. more information. Trying to call svgElement.focus()
on IE11 will cause an exception. There are also additional concerns:
- Applying
aria-*
to a<svg>
has unknown screen reader implications. - Inconsistent
tabindex
behaviour in older browsers
One of the core values of react-beautiful-dnd
is accessibility
Beautiful and accessible drag and drop for lists with
React
In order to provide the best accessibility and cross browser experience for consumers we enforce that SVGElement
s need to be wrapped in a HTMLElement
such as <span>
or <div>
if you want to have them as your <Draggable />
or drag handle.
// ❌ not supported
<Draggable draggableId="not-supported" index={0}>
{provided => (
<svg
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
{/* other SVG stuff */}
/>
)}
</Draggable>
// ✅ supported
<Draggable draggableId="supported" index={0}>
{provided => (
<span
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<svg {/* other SVG stuff */} />
</span>
)}
</Draggable>
You can use the src
of an <img>
tag (which is a HTMLElement
) to have a draggable SVG.
// ✅ supported
<Draggable draggableId="supported" index={0}>
{provided => (
<img
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
src="my-cool-image.svg"
/>
)}
</Draggable>
You can read more about this approach on CSS-Tricks
Alternatively you could also apply the SVG as a background-image
to another HTMLElement
.
.item {
background-image: url(my-cool-image.svg);
}
// ✅ supported
<Draggable draggableId="supported" index={0}>
{provided => (
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
className="item"
/>
)}
</Draggable>
You can read more about this approach on CSS-Tricks