Image elements

Add image elements to designs with editing capabilities.

Running this example

To run this example locally:

  1. If you haven't already, create a new app in the Developer Portal(opens in a new tab or window). For more information, refer to our Quickstart guide.

  2. In your app's configuration on the Developer Portal(opens in a new tab or window), ensure the "Development URL" is set to http://localhost:8080.

  3. Clone the starter kit:

    git clone https://github.com/canva-sdks/canva-apps-sdk-starter-kit.git
    cd canva-apps-sdk-starter-kit
    SHELL
  4. Install dependencies:

    npm install
    SHELL
  5. Run the example:

    npm run start image_elements
    SHELL
  6. Click the Preview URL link shown in the terminal to open the example in the Canva editor.

Example app source code

// For usage information, see the README.md file.
/* eslint-disable no-restricted-imports */
import {
Box,
Button,
FormField,
Grid,
ImageCard,
Rows,
Text,
} from "@canva/app-ui-kit";
import cat from "assets/images/cat.jpg";
import dog from "assets/images/dog.jpg";
import rabbit from "assets/images/rabbit.jpg";
import { useState, useCallback } from "react";
import * as styles from "styles/components.css";
import { upload } from "@canva/asset";
import { useAddElement } from "utils/use_add_element";
const images = {
dog: {
title: "Dog",
imageSrc: dog,
},
cat: {
title: "Cat",
imageSrc: cat,
},
rabbit: {
title: "Rabbit",
imageSrc: rabbit,
},
};
export const App = () => {
const [dataUrl, setDataUrl] = useState(dog);
const [isLoading, setIsLoading] = useState(false);
const addElement = useAddElement();
const disabled = !dataUrl || dataUrl.trim().length < 1;
const items = Object.entries(images).map(([key, value]) => {
const { title, imageSrc } = value;
return {
key,
title,
imageSrc,
active: dataUrl === imageSrc,
onClick: () => {
setDataUrl(imageSrc);
},
};
});
const addImage = useCallback(async () => {
setIsLoading(true);
try {
const { ref } = await upload({
type: "image",
mimeType: "image/jpeg",
url: dataUrl,
thumbnailUrl: dataUrl,
aiDisclosure: "none",
});
await addElement({
type: "image",
ref,
altText: {
text: "photo of an animal",
decorative: undefined,
},
});
} finally {
setIsLoading(false);
}
}, [dataUrl, addElement]);
return (
<div className={styles.scrollContainer}>
<Rows spacing="2u">
<Text>
This example demonstrates how apps can add image elements to a design.
</Text>
<FormField
label="Select an image"
control={({ id }) => (
<Box id={id} padding="1u">
<Grid columns={3} spacing="1.5u">
{items.map((item) => (
<ImageCard
ariaLabel="Add image to design"
alt={item.title}
key={item.key}
thumbnailUrl={item.imageSrc}
onClick={item.onClick}
selectable={true}
selected={item.active}
borderRadius="standard"
/>
))}
</Grid>
</Box>
)}
/>
<Button
variant="primary"
disabled={disabled}
loading={isLoading}
onClick={addImage}
stretch
>
Add element
</Button>
</Rows>
</div>
);
};
TYPESCRIPT
import { AppUiProvider } from "@canva/app-ui-kit";
import { createRoot } from "react-dom/client";
import { App } from "./app";
import "@canva/app-ui-kit/styles.css";
const root = createRoot(document.getElementById("root") as Element);
function render() {
root.render(
<AppUiProvider>
<App />
</AppUiProvider>,
);
}
render();
if (module.hot) {
module.hot.accept("./app", render);
}
TYPESCRIPT
# Image elements example
This example demonstrates how to add image elements to a design.
For API reference docs and instructions on running this example, see: https://www.canva.dev/docs/apps/examples/image-elements/.
See also the App image elements example: https://www.canva.dev/docs/apps/examples/app-image-elements/. Using app elements instead of regular design elements allows for more complex app interactions and behaviors.
NOTE: This example differs from what is expected for public apps to pass a Canva review:
- Static assets are used for demonstration purposes only. Production apps should host assets on a CDN/hosting service and use the `upload` function from the `@canva/asset` package
- ESLint rule `no-restricted-imports` is disabled for example purposes only. Production apps should not disable linting rules without proper justification
- Error handling is simplified for demonstration. Production apps must implement comprehensive error handling with clear user feedback and graceful failure modes
- Internationalization is not implemented. Production apps must support multiple languages using the `@canva/app-i18n-kit` package to pass Canva review requirements
MARKDOWN

API Reference

Need Help?