Skip to content

UI & layout

The editor's chrome is arranged from a few independent pieces. This page explains each and the properties that position them. Every option here is an attribute, so you can set it in HTML or as a property, and you can try them all live on the demo.

The pieces

  • Canvas. The central stage where the image (or the idle dot grid) is shown.
  • Composer. The bar holding the prompt input, the preset chips, and the aspect-ratio picker. It's where the user types to generate or edit.
  • History strip. The row of result thumbnails from the current session.
  • Toolbar. The Cancel and Done actions.

Sizing

sizing decides who owns the editor's height:

ValueResult
fill (default)The editor fills the box you give it. Size the host element explicitly with CSS.
contentYou fix the width; the editor derives its own height from the active aspect ratio, within your min-height / max-height.

Fill (default)

Give the element a concrete box — the editor fills it, and the canvas letterboxes the image inside:

css
uc-ai-image-editor {
  max-width: 1200px;
  height: min(82vh, 820px);
}

An unsized host falls back to a 480px minimum height instead of collapsing; your own CSS on the element always wins over that fallback.

Content-driven height

With sizing="content" the editor grows and shrinks with the image: at the width you set, its height follows the aspect ratio currently on canvas — the picker selection while composing, the result's own ratio once one exists — plus the composer/toolbar chrome. Constrain it with plain CSS on the host:

html
<uc-ai-image-editor sizing="content"></uc-ai-image-editor>
css
uc-ai-image-editor {
  width: 720px;
  min-height: 360px;
  max-height: 85vh;
}

When a tall result would exceed your max-height, the editor stops growing and the canvas letterboxes the image inside — exactly like fill mode. Height changes (a new ratio pick, a differently-shaped result) animate in sync with the canvas frame.

Composer position

composerPlacement picks which edge the composer sits on:

html
<uc-ai-image-editor composer-placement="top"></uc-ai-image-editor>
ValueResult
bottom (default)Composer along the bottom edge.
topComposer along the top edge.

Canvas fit: docked vs. floating

canvasFit decides whether the composer sits outside the image or floats over it:

ValueResult
available (default)The canvas shrinks to the space left by the composer, which is docked outside the image.
fullThe canvas fills the whole area and the composer floats over it as an overlay.
html
<uc-ai-image-editor canvas-fit="full"></uc-ai-image-editor>

History strip position

historyPlacement places the result-thumbnail strip either relative to the composer or pinned to a canvas edge:

ValueResult
composer-above (default)Just above the composer (moves with it).
composer-belowJust below the composer.
canvas-topPinned to the top edge of the canvas.
canvas-bottomPinned to the bottom edge of the canvas.

Toolbar position

toolbarPlacement sets the edge for the Cancel / Done toolbar, either bottom (the default) or top. Setting it to none removes the toolbar entirely.

html
<uc-ai-image-editor toolbar-placement="top"></uc-ai-image-editor>

Bring your own toolbar

With toolbar-placement="none" the editor renders no Cancel or Done buttons. The stage reclaims their space, and your app provides the controls. Track the current result via the uc:change event, which fires whenever the result changes: a finished generation, a history-strip selection, or Start over, in which case detail.result is null. The payload has the same shape as uc:done (url, uuid, prompt, mode, aspectRatio, file). Every result is already an uploaded Uploadcare file, so result.file and result.url are usable immediately. Nothing about them waits for a "commit".

html
<uc-ai-image-editor pubkey="YOUR_PUBLIC_KEY" toolbar-placement="none"></uc-ai-image-editor>
<button id="use" disabled>Use this image</button>
js
const editor = document.querySelector('uc-ai-image-editor');
const useBtn = document.querySelector('#use');

let current = null;
editor.addEventListener('uc:change', (e) => {
  current = e.detail.result; // DoneDetail | null
  useBtn.disabled = current === null;
});
useBtn.addEventListener('click', () => {
  save(current.url); // then close/remove the editor yourself
});

Closing is yours too. With no toolbar, uc:done and uc:cancel never fire, since their buttons are the only triggers. Use uc:change as the source of truth and remove or hide the editor whenever your UI decides the session is over.

In React the same pattern is the onChange prop; see the React guide.

Presets-only mode

presets-only hides the free-text prompt so only the preset chips remain, and picking a chip starts the generation immediately (there's nothing to type, so no separate send step). Pair it with custom presets per mode.

html
<uc-ai-image-editor presets-only></uc-ai-image-editor>

Putting it together

These axes are orthogonal, so mix them freely. For example, a floating composer pinned to the top, with the history along the bottom of the canvas:

html
<uc-ai-image-editor
  composer-placement="top"
  canvas-fit="full"
  history-placement="canvas-bottom"
  toolbar-placement="top"
></uc-ai-image-editor>

See every property in the Components API.