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
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.
| Field | Type | Default | Description |
|---|---|---|---|
order | Read-only id array | Surface order | Puts listed ids first, preserving the order of unlisted entries afterward. |
hidden | Read-only id array | None | Removes listed controls from this surface. |
labels | Map of id to string | Built-in labels | Replaces the visible label, tooltip and accessible name. |
display | Map of id to icon, label or both | Surface display | Changes 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,lockandunlock, are at the end of every desktop list. In the lists below they are written as...OBJECT_CONTROLS.lockis the Lock… button andunlockis 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.
copyStyleandpasteStyleare not in any list. They are always in More. Name them inui.selection.orderto 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:
| Id | What it does |
|---|---|
replace | Puts a new file in place of the selected picture and keeps its position and size. |
copyStyle, pasteStyle | Copy the look of one item, and give it to others. See Copy style and paste style. |
group, ungroup | For 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 type | Ids |
|---|---|
ImageToolRailId | elements, photo, upload, text, brand, shapes, stickers, templates, effects, background, automated |
ImageDockId | photo, media, text, brand, elements, shapes, stickers, background, effects, resize, templates, automated |
ImageSelectionChipId | editWithAi, 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.