Supporting drag and drop

How to support drag and drop in an app.

Throughout Canva, users can drag and drop content into their designs. You can use the Apps SDK to implement this behavior, allowing your app to offer a consistently delightful experience.

Check out the Drag and drop design guidelines

Our design guidelines help you create a high-quality app that easily passes app review.

When a user drags content into a design, the content moves through three states:

  • Idle
  • Dragging
  • Dropped

The idle state is when the content is in the object panel, waiting for the user to interact with it.

The dragging state is when the content is being dragged into the user's design. In this state, a semi-transparent preview of the content is shown under the user's cursor. Typically, the content in the object panel is made invisible while it's being dragged. This creates the effect of the content being moved.

The dropped state is when the content is added to the user's design. If the content was made invisible in the object panel, it's made visible again.

For accessibility reasons and cross-platform support, all content that can be dragged and dropped into a design must also support clicking as a means of creating elements.

When using the Apps SDK, only certain types of content can be created via drag and drop, including:

The following types of content are not supported:

In the starter kit, we've included React components for creating draggable content:

Using these components is the easiest way to support draggable content and, in most cases, we recommend using them instead of the underlying APIs.

  1. Create the node that will be made draggable, such as a div or img node:

    import React from "react";
    export function App() {
    return <div>Drag and drop me into a design</div>;
    }
  2. Add a draggable attribute to the node:

    <div draggable={true}>Drag and drop me into a design</div>

    The draggable attribute is a standard HTML feature that allows the node to be dragged, but additional steps are required to complete the integration with Canva.

Use the useRef hook to grab a reference to the node:

import React from "react";
export function App() {
const ref = React.useRef<HTMLDivElement>(null);
return (
<div ref={ref} draggable={true}>
Drag and drop me into a design
</div>
);
}

This lets the app directly interact with the node, which is necessary for the next step.

Import the ui namespace from the @canva/design package:

import { ui } from "@canva/design";

This namespace exposes a makeDraggable method that makes Canva aware of a node as it's being dragged and dropped. The method accepts a dragData object that defines what will be added to the user's design at the end of the drag event.

The expected properties for the makeDraggable method depend on what's being added to the design:

  • Audio tracks
  • Images
  • Text
  • Videos

The following snippet demonstrates how to add an audio track to the user's design:

import React from "react";
import { ui } from "@canva/design";
import { upload } from "@canva/asset";
export function App() {
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (!ref?.current) {
return;
}
ui.makeDraggable({
node: ref.current,
dragData: {
type: "AUDIO",
resolveAudioRef: () => {
return upload({
type: "AUDIO",
id: "uniqueidgoeshere",
title: "Example audio",
url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",
mimeType: "audio/mp3",
durationMs: 86047,
});
},
title: "Example audio",
durationMs: 86047,
},
onDragStart: () => {
console.log("The drag event has started");
},
onDragEnd: () => {
console.log("The drag event has ended");
},
});
}, [ref]);
return (
<div ref={ref} draggable={true}>
Drag and drop me into a design
</div>
);
}

For a complete description of the available properties, see the API reference.

The makeDraggable method accepts two callback functions:

  • onDragStart
  • onDragEnd

These callback functions run at the start and end of a drag event, respectively.

A use-case for these functions is to hide the draggable node at the start of a drag event and show it again at the end of a drag event. This creates the illusion of the node being moved from one location to another, rather than copied, which is consistent with the native Canva experience.

  • Users can only drag and drop content on desktop devices. If an app supports mobile devices, it will need to ensure that content can also be added with a click or a tap.
  • Only one piece of content can be dragged into a design at a time.