Render rich controls with JSX (and TypeScript)
Learn how to render rich controls with JSX and TypeScript.
The typical way to render controls in a frontend extension is with the canva.create method:
1
canva.create("button", {
2
id: "myButton",
3
label: "Click me!",
4
});
Copied!
But it's also possible to render controls with the JSX syntax:
1
<Button id="myButton" label="Click me!" key="myButton" />
Copied!
This tutorial explains how to configure a TypeScript project to support the JSX syntax.
If you're using JavaScript, see Render controls with JSX and JavaScript.

Prerequisites

Step 1: Install the TypeScript definitions

To render controls with JSX, an extension needs the following TypeScript definitions:
To install these definitions, run the following command:
1
npm install @canva/editing-extensions-api-typings @types/react --save-dev
2
# yarn add @canva/editing-extensions-api-typings @types/react --dev
Copied!

Step 2: Enable JSX compilation

By default, TypeScript doesn't compile JSX into JavaScript. To enable the feature, set the jsx option in the tsconfig.json file to "react":
1
{
2
"compilerOptions": {
3
"jsx": "react"
4
}
5
}
Copied!
If you followed the instructions for setting up a Development URL, these dependencies are already installed.

Step 3: Create a tsx file for the controls

TypeScript only compiles JSX in files that have a tsx extension. Because of this, we recommend creating a renderControls function in a separate controls.tsx file:
1
import { EditingExtensionClient } from "@canva/editing-extensions-api-typings";
2
3
export const renderControls = (canva: EditingExtensionClient.API) => {
4
const controls = [
5
// JSX controls go here
6
];
7
canva.updateControlPanel(controls);
8
};
Copied!
You can then import and call this function from the app's entry point:
1
import { EditingExtensionClient } from "@canva/editing-extensions-api-typings";
2
import { renderControls } from "./controls";
3
4
const canva: EditingExtensionClient.API = window.canva.init();
5
6
canva.onReady(async (opts) => {
7
renderControls(canva);
8
});
Copied!
The canva variable must be available in the same context as the JSX syntax.
If you simply rename ts files with the tsx extension, you may end up with errors, as TypeScript parses each type of file (a little) differently.

Step 4: Add the JSX pragma to the source code

At the top of the tsx file, add the following comment:
1
/** @jsx canva.create */
Copied!
During the build process, TypeScript "sees" this comment and converts the JSX controls into the canva.create syntax.
To see an example of this compilation:
  1. 1.
    Navigate to the TypeScript Playground.
  2. 2.
    In the TS Config menu, select React from the JSX dropdown.
  3. 3.
    Copy the following code into the editor:
    1
    /** @jsx canva.create */
    2
    <Button id="myButton" label="My Button" key="123" />
    Copied!
The compiled code resembles the following:
1
"use strict";
2
/** @jsx canva.create */
3
canva.create(Button, {
4
id: "myButton",
5
label: "My Button",
6
key: "123",
7
});
Copied!
JSX controls must have a unique key property.

Step 5: Use a JSX control

To use a JSX control, import the control into the tsx file:
1
import { Button } from "@canva/editing-extensions-api-typings/lib/jsx";
Copied!
Then render it via the renderControls function:
1
export const renderControls = (canva: EditingExtensionClient.API) => {
2
const controls = [<Button id="myButton" label="My Button" key="myButton" />];
3
canva.updateControlPanel(controls);
4
};
Copied!
If a control has a children property, such as the Group control, wrap the JSX element around the children elements:
1
export const renderControls = (canva: EditingExtensionClient.API) => {
2
const controls = [
3
<Group id="group1" label="Group #1" key="group1">
4
<Button id="button1" label="Button #1" key="button1" />
5
<Button id="button2" label="Button #2" key="button2" />
6
<Button id="button3" label="Button #3" key="button3" />
7
</Group>,
8
];
9
canva.updateControlPanel(controls);
10
};
Copied!

Step 6: Compile with TypeScript

To compile the TypeScript into JavaScript, run the build command:
1
npm run build
2
# yarn build
Copied!
In the compiled code, the JSX is replaced with the canva.create method.

Example

controls.tsx

1
/** @jsx canva.create */
2
import { EditingExtensionClient } from "@canva/editing-extensions-api-typings";
3
import { Button, Group } from "@canva/editing-extensions-api-typings/lib/jsx";
4
5
export const renderControls = (canva: EditingExtensionClient.API) => {
6
const controls = [
7
<Group id="group1" label="Group #1" key="group1">
8
<Button id="button1" label="Button #1" key="button1" />
9
<Button id="button2" label="Button #2" key="button2" />
10
<Button id="button3" label="Button #3" key="button3" />
11
</Group>,
12
];
13
canva.updateControlPanel(controls);
14
};
Copied!

index.ts

1
import { EditingExtensionClient } from "@canva/editing-extensions-api-typings";
2
import { renderControls } from "./controls";
3
4
const canva: EditingExtensionClient.API = window.canva.init();
5
6
canva.onReady(async (opts) => {
7
renderControls(canva);
8
});
Copied!

tsconfig.json

1
{
2
"compilerOptions": {
3
"jsx": "react"
4
}
5
}
Copied!
Last modified 27d ago