Control customization

Hide, reorder and relabel built-in editor controls

ui.selection configures the controls of the selected item: the bar above the canvas on a desktop, and the selection bar on a phone. ui.toolRail and ui.dock configure the tools on the left and at the bottom. ui.toolbar is the older setting for the toolbar groups. It still works, and the editor translates it.

Usage

src/App.tsx
import { ImageEditor, type ItemListConfig, type ImageSelectionChipId } from '@layermetry/media-editor/react';

const selection: ItemListConfig<ImageSelectionChipId> = {
  order: ['crop', 'effects'],
  hidden: ['delete'],
  labels: { crop: 'Trim edges' },
  display: { effects: 'icon' },
};

export default function App() {
  return <div style={{ position: 'fixed', inset: 0 }}>
    <ImageEditor licenseKey="YOUR_LICENSE_KEY" onClose={() => undefined}
      ui={{
        selection,
        toolRail: { display: { text: 'both' } },
        dock: { display: { photo: 'icon' } },
      }} />
  </div>;
}

These settings change the controls that are currently available. They do not make an unsupported control appear for another item type.

List settings

All four settings use ItemListConfig: ui.toolRail, ui.dock, ui.selection and ui.toolbar.

FieldTypeDefaultDescription
orderRead-only id arraySurface orderPuts listed ids first, preserving the order of unlisted entries afterward.
hiddenRead-only id arrayNoneRemoves listed controls from this surface.
labelsMap of id to stringBuilt-in labelsReplaces the visible label, tooltip and accessible name.
displayMap of id to icon, label or bothSurface displayChanges how each entry is drawn.

ui.selection applies to the bar above the canvas on a desktop, and to the selection bar and the small pill on a phone. It names controls by id, so one id applies to every type of item that has that control. ui.toolbar is the older setting. It names toolbar groups, such as Format and Images. See The old ui.toolbar setting.

An icon-only control keeps its label as a tooltip and accessible name. The right-click menu always shows words. Hiding a control removes only that control: shortcuts and programmatic editing actions remain available. Each surface is configured independently. Use roles and locks to restrict editing permissions.

Default lists

Each default order is a plain list in the editor. It is the starting view, and your ui.selection is applied after it, so your choice always wins. The lists below are the real defaults. Copy a list, change it, and pass it as ui.selection.order.

How to read a list:

  • Left to right is the order on the screen. It is also the priority. When the desktop bar runs out of width, the controls at the end of the list move into More first.
  • A control that the editor can show, but that a list does not name, is kept after the named controls. No control disappears because it is missing from a list.
  • The last five ids, bringForward, sendBackward, delete, lock and unlock, are at the end of every desktop list. In the lists below they are written as ...OBJECT_CONTROLS. lock is the Lock… button and unlock is the Unlock button. Each one shows only when it is available for the selection.
  • A control shows only when it fits the item. Naming an id in a list does not make a control appear for an item that cannot use it.
  • copyStyle and pasteStyle are not in any list. They are always in More. Name them in ui.selection.order to bring them into the bar.

The keys are the types of item. multi is for several items selected together. A picture, a sticker and a GIF share one list.

The bar above the canvas on a desktop:

const OBJECT_CONTROLS = ['bringForward', 'sendBackward', 'delete', 'lock', 'unlock'];

const desktopBar = {
  text: [
    'font', 'fontSize', 'textColor', 'bold', 'italic', 'underline', 'textAlign', 'textStyles',
    'effects', 'opacity', 'rewriteWithAi', 'editText', ...OBJECT_CONTROLS,
  ],
  shape: [
    'fill', 'stroke', 'strokeWidth', 'effects', 'opacity', ...OBJECT_CONTROLS,
  ],
  image: [
    'crop', 'mask', 'removeBg', 'fitOptions', 'replace', 'effects', 'opacity', 'clearCrop',
    'clearMask', 'editWithAi', ...OBJECT_CONTROLS,
  ],
  sticker: [
    'crop', 'mask', 'removeBg', 'fitOptions', 'replace', 'effects', 'opacity', 'clearCrop',
    'clearMask', 'editWithAi', ...OBJECT_CONTROLS,
  ],
  gif: [
    'crop', 'mask', 'removeBg', 'fitOptions', 'replace', 'effects', 'opacity', 'clearCrop',
    'clearMask', 'editWithAi', ...OBJECT_CONTROLS,
  ],
  label: [
    'editText', 'labelColor', 'opacity', ...OBJECT_CONTROLS,
  ],
  multi: [
    'group', 'ungroup', 'opacity', ...OBJECT_CONTROLS,
  ],
};

On a phone, only several selected items have a default list. Every other type keeps the order that the editor builds:

const phoneBar = {
  multi: [
    'delete', 'bringForward', 'sendBackward', 'opacity', 'group', 'ungroup', 'lock', 'unlock',
  ],
};

By default the desktop bar draws bold, italic, underline, bringForward, sendBackward and delete as a picture only, because the picture says enough and the words would cost the width of two other buttons. The label is still the tooltip and the accessible name. Set display for the id to 'label' or 'both' to bring the words back.

This example puts Replace and Crop first, hides Delete, and shows the words on Replace:

import type { ImageUiConfig } from '@layermetry/media-editor';

const ui: ImageUiConfig = {
  selection: {
    order: ['replace', 'crop'],
    hidden: ['delete'],
    display: { replace: 'both' },
  },
};

New ids in this release:

IdWhat it does
replacePuts a new file in place of the selected picture and keeps its position and size.
copyStyle, pasteStyleCopy the look of one item, and give it to others. See Copy style and paste style.
group, ungroupFor several selected items.

The old ui.toolbar setting

ui.toolbar is still accepted, but the bar above the canvas has no groups or headings now. The editor translates each group id into the controls that the group held, for the item types that showed it. hidden and order are applied to those controls, together with your ui.selection.

A labels setting, or a display of 'label' or 'both', has no heading left to change. Your own buttons are the group actions. They always come after the editor's controls with no heading. Hiding actions still works. The order, labels and display of actions are not applied.

Hiding controls with ui.toolbar.hidden also hides the page-bar extras: Save template and Default locks…. The page controls and More stay visible.

The editor prints one console warning that starts with [MediaEditor] ui.toolbar:. It names what was translated and what has no effect, and it tells you to use ui.selection. Use ui.selection with the control ids in new code.

Control ids

Use the union for the surface you want to configure.

Public typeIds
ImageToolRailIdelements, photo, upload, text, brand, shapes, stickers, templates, effects, background, automated
ImageDockIdphoto, media, text, brand, elements, shapes, stickers, background, effects, resize, templates, automated
ImageSelectionChipIdeditWithAi, rewriteWithAi, editText, font, fontSize, bold, italic, underline, textColor, textAlign, textStyles, fill, stroke, strokeWidth, fitOptions, crop, clearCrop, mask, clearMask, removeBg, effects, opacity, labelColor, openBackground, bringForward, sendBackward, delete, lock, unlock, replace, group, ungroup, copyStyle, pasteStyle
ImageToolbarGroupId (old setting)text, format, style, shapes, images, actions, controls

Effects and Background are not on the tool rail by default. List an id in ui.toolRail.order to bring it back. See Tools that are off the rail by default.

The main ui fields accept strings so you can share a configuration between editors. To check ids at compile time, use ItemListConfig with the ImageSelectionChipId type argument or the corresponding union above. An unknown id is ignored with one console warning. Available controls still depend on the selected item and enabled features.

Custom action controls

Use ui.customActions.shown for custom-action overflow counts. Your own buttons come after the editor's controls on the bar above the canvas, and ui.toolbar.hidden can still hide them with the id actions. See Custom actions.

On this page