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 App UI Kit, we've provided a number of card components for rendering content thumbnails, such as images and videos. These components are designed to work seamlessly with Canva's drag and drop APIs.

The components include:

We generally recommend using these components as they look good, enforce best practices, and are the easiest way to get up and running with draggable content.

The following code samples demonstrate how to use the components:

import { AudioCard, AudioContextProvider, Rows } from "@canva/app-ui-kit";
import { upload } from "@canva/asset";
import { addAudioTrack, ui } from "@canva/design";
import React from "react";
import styles from "styles/components.css";
export function App() {
async function handleClick() {
const audioAsset = await upload({
type: "AUDIO",
id: "uniqueIdGoesHere",
title: "Example audio",
mimeType: "audio/mp3",
durationMs: 86047,
url: "",
ref: audioAsset.ref,
function handleDragStart(event: React.DragEvent<HTMLElement>) {
ui.startDrag(event, {
type: "AUDIO",
title: "Example audio",
durationMs: 86047,
resolveAudioRef: () => {
return upload({
type: "AUDIO",
id: "uniqueIdGoesHere",
title: "Example audio",
mimeType: "audio/mp3",
durationMs: 86047,
url: "",
return (
<div className={styles.scrollContainer}>
<Rows spacing="1u">
{/* A single `AudioContextProvider` component must be an ancestor to all `AudioCard` components*/}
title="Example audio"
  • 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.