> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://uploadcare.com/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://uploadcare.com/docs/_mcp/server.

# AI Image Editor UI & layout

> Position the composer, history strip, and toolbar of the AI Image Editor editor, or remove the toolbar and bring your own chrome.

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.

## 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]

[`sizing`](/docs/ai-image-editor/options/#sizing) decides who owns the editor's
height:

| Value              | Result                                                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `fill` *(default)* | The editor fills the box you give it. Size the host element explicitly with CSS.                                                |
| `content`          | You 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;
}
```

The canvas letterboxes whenever those limits clamp the derived height.

## Composer position

[`composerPlacement`](/docs/ai-image-editor/options/#composer-placement) picks
which edge the composer sits on:

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

| Value                | Result                          |
| -------------------- | ------------------------------- |
| `bottom` *(default)* | Composer along the bottom edge. |
| `top`                | Composer along the top edge.    |

## Canvas fit: docked vs. floating

[`canvasFit`](/docs/ai-image-editor/options/#canvas-fit) decides whether the
composer sits **outside** the image or **floats over** it:

| Value                   | Result                                                                                       |
| ----------------------- | -------------------------------------------------------------------------------------------- |
| `available` *(default)* | The canvas shrinks to the space left by the composer, which is **docked** outside the image. |
| `full`                  | The 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`](/docs/ai-image-editor/options/#history-placement) places the
result-thumbnail strip either relative to the composer or pinned to a canvas
edge:

| Value                        | Result                                   |
| ---------------------------- | ---------------------------------------- |
| `composer-above` *(default)* | Just above the composer (moves with it). |
| `composer-below`             | Just below the composer.                 |
| `canvas-top`                 | Pinned to the top edge of the canvas.    |
| `canvas-bottom`              | Pinned to the bottom edge of the canvas. |

## Toolbar position

[`toolbarPlacement`](/docs/ai-image-editor/options/#toolbar-placement) 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 \[#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](/docs/ai-image-editor/react/#events).

## Presets-only mode

[`presetsOnly`](/docs/ai-image-editor/options/#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`](/docs/ai-image-editor/options/#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 option on the [Options](/docs/ai-image-editor/options/) page.