Preset categories

Organize presets into labelled categories.

An editing extension can organize presets into categories. This creates a visual hierarchy that helps users navigate a large number of presets.

This tutorial explains how to organize presets into categories.

Step 1: Assign a category to each preset

In the onPresetsRequest callback, provide a categoryId property for each preset:

canva.onPresetsRequest(async (opts) => {
return [
{
id: 'invert',
label: 'Invert',
image: opts.image,
kind: 'simple',
categoryId: 'categoryOne',
},
{
id: 'grayscale',
label: 'grayscale',
image: opts.image,
kind: 'simple',
categoryId: 'categoryTwo',
},
{
id: 'sepia',
label: 'Sepia',
image: opts.image,
kind: 'simple',
categoryId: 'categoryTwo',
},
];
});

This property must be a string that uniquely identifies a category. When presets have the same value for the categoryId property, Canva arranges them into groups.

If any preset has a category, they all must have a category.

Step 2: Set up a localized label for each category

Each categoryId must correspond to the key of a localized label. Canva uses these labels to render headings for each category.

The following snippet provides an example of a localized label file:

{
"en": [
{
"key": "categoryOne",
"value": "Category #1",
"translatorNote": "Label of the first category."
},
{
"key": "categoryTwo",
"value": "Category #2",
"translatorNote": "Label of the second category."
}
]
}

By uploading a localized labels file to the extension via the Developer Portal, Canva can translate the labels for a variety of locales.

Example

index.js

const { imageHelpers } = window.canva;
const canva = window.canva.init();
const state = {
image: null,
canvas: null,
selectedPreset: null,
};
canva.onReady(async (opts) => {
// Download the user's image
state.image = await imageHelpers.fromElement(opts.element);
// Convert the user's image into a HTMLCanvasElement
state.canvas = await imageHelpers.toCanvas(state.image);
// Render the user's image
document.body.appendChild(state.canvas);
if (opts.presetId) {
// Keep track of the selected preset
state.selectedPreset = opts.presetId;
// Render the user's image with preset applied
await renderImage();
}
});
canva.onPresetsRequest(async (opts) => {
return [
{
id: 'invert',
label: 'Invert',
image: opts.image,
kind: 'simple',
categoryId: 'categoryOne',
},
{
id: 'grayscale',
label: 'Grayscale',
image: opts.image,
kind: 'simple',
categoryId: 'categoryTwo',
},
{
id: 'sepia',
label: 'Sepia',
image: opts.image,
kind: 'simple',
categoryId: 'categoryTwo',
},
];
});
canva.onPresetSelected(async (opts) => {
// Keep track of the selected preset
state.selectedPreset = opts.presetId;
// Re-render the image when a user selects a preset
await renderImage();
});
canva.onImageUpdate(async (opts) => {
// Handle image update requests from Canva
state.image = opts.image;
await renderImage();
});
canva.onSaveRequest(async () => {
// Return the image to Canva
return await imageHelpers.fromCanvas('image/jpeg', state.canvas);
});
async function renderImage() {
const img = await imageHelpers.toImageElement(state.image);
const context = state.canvas.getContext('2d');
if (state.selectedPreset === 'invert') {
context.filter = `invert(100%)`;
}
if (state.selectedPreset === 'grayscale') {
context.filter = `grayscale(100%)`;
}
if (state.selectedPreset === 'sepia') {
context.filter = `sepia(100%)`;
}
context.drawImage(img, 0, 0, state.canvas.width, state.canvas.height);
}

labels.json

{
"en": [
{
"key": "categoryOne",
"value": "Category #1",
"translatorNote": "Label of the first category."
},
{
"key": "categoryTwo",
"value": "Category #2",
"translatorNote": "Label of the second category."
}
]
}