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>;
    }
    tsx
  2. Add a draggable attribute to the node:

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

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

  3. Add an onDragStart attribute to the node:

    <div
    draggable={true}
    onDragStart={(event) => {
    console.log(event);
    }}
    >
    Drag and drop me into a design
    </div>
    tsx

    This attribute accepts a callback that receives an event parameter.

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

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

    This namespace exposes a ui.startDrag method that makes Canva aware of a node as it's dragged.

  5. In the onDragStart callback, call the ui.startDrag method with the event object as the first argument:

    <div
    draggable={true}
    onDragStart={(event) => {
    ui.startDrag(event);
    }}
    >
    Drag and drop me into a design
    </div>
    tsx
  6. As the second argument of the ui.startDrag method, pass in an object that defines the element to add to the design at the end of the drag event. The expected properties depend on the type of element:

    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() {
    return (
    <div
    draggable={true}
    onDragStart={(event) => {
    ui.startDrag(event, {
    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,
    });
    }}
    >
    Drag and drop me into a design
    </div>
    );
    }
    tsx
  • 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.