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, the floating pill, 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 { VideoEditor, type ItemListConfig, type SelectionChipId } from '@layermetry/media-editor/react';
const selection: ItemListConfig<SelectionChipId> = {
order: ['crop', 'effects'],
hidden: ['delete'],
labels: { crop: 'Trim edges' },
display: { effects: 'icon' },
};
export default function App() {
return <div style={{ position: 'fixed', inset: 0 }}>
<VideoEditor licenseKey="YOUR_LICENSE_KEY" onClose={() => undefined}
ui={{
selection,
toolRail: { display: { text: 'both' } },
dock: { display: { media: '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, the floating pill, the selection bar on a phone, 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. For example,
removeBgneeds a picture or a clip. 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.
The bar above the canvas on a desktop:
const OBJECT_CONTROLS = ['bringForward', 'sendBackward', 'delete', 'lock', 'unlock'];
const desktopBar = {
video: [
'trim', 'split', 'speed', 'volume', 'mute', 'crop', 'mask', 'effects', 'animations',
'audioFx', 'captions', 'fades', 'fitMode', 'opacity', 'replace', 'clearCrop', 'clearMask',
'removeBg', 'stabilize', 'generateCaptions', 'position', 'fitToCanvas', 'matchCanvas',
...OBJECT_CONTROLS,
],
audio: [
'trim', 'split', 'speed', 'volume', 'mute', 'fades', 'audioFx', 'reRecordPart', 'replace',
'position', ...OBJECT_CONTROLS,
],
text: [
'font', 'fontSize', 'textColor', 'bold', 'italic', 'underline', 'textAlign', 'textStyles',
'effects', 'animations', 'opacity', 'rewriteWithAi', 'editText', 'textBackgrounds',
'position', ...OBJECT_CONTROLS,
],
shape: [
'fill', 'stroke', 'strokeWidth', 'effects', 'animations', 'opacity', 'position',
...OBJECT_CONTROLS,
],
image: [
'crop', 'mask', 'removeBg', 'fitMode', 'replace', 'effects', 'animations', 'opacity',
'clearCrop', 'clearMask', 'editWithAi', 'makeVideo', 'position', 'fitToCanvas',
'matchCanvas', ...OBJECT_CONTROLS,
],
sticker: [
'mask', 'effects', 'animations', 'opacity', 'clearMask', 'position', ...OBJECT_CONTROLS,
],
gif: [
'mask', 'animations', 'opacity', 'clearMask', 'matchCanvas', 'position',
...OBJECT_CONTROLS,
],
label: [
'editText', 'textColor', 'animations', 'opacity', 'position', ...OBJECT_CONTROLS,
],
subtitle: [
'subtitleStyle', 'subtitleTextColor', 'subtitleBgColor', 'subtitleFont',
'subtitleFontSize', 'subtitlePosition', 'align', 'bgOpacity', 'stroke', 'shadow',
'subtitleAnimation', 'captions', 'position', ...OBJECT_CONTROLS,
],
multi: [
'group', 'ungroup', 'position', 'opacity', 'animations', 'viewRecommendations',
...OBJECT_CONTROLS,
],
};On a phone, only a video clip and a sound clip have a default list. Every other type keeps the order that the editor builds:
const phoneBar = {
video: [
'trim', 'split', 'speed', 'volume', 'mute', 'crop', 'clearCrop', 'mask', 'clearMask',
'effects', 'animations', 'fitMode', 'replace', 'audioFx', 'captions', 'generateCaptions',
'fades', 'opacity', 'position', 'fitToCanvas', 'matchCanvas', 'removeBg', 'stabilize',
],
audio: [
'volume', 'audioFx', 'reRecordPart', 'split', 'speed', 'fades', 'trim', 'mute', 'replace',
'position',
],
};By default the desktop bar draws bold, italic, underline, bringForward, sendBackward, delete and mute 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 Mute and Trim first, hides Delete, and shows the words on Mute:
import type { UiConfig } from '@layermetry/media-editor';
const ui: UiConfig = {
selection: {
order: ['mute', 'trim'],
hidden: ['delete'],
display: { mute: 'both' },
},
};New ids in this release:
| Id | What it does |
|---|---|
trim | Video and sound clips. Sets where the clip starts in its file and how long it lasts, with the same limits as dragging the edges on the timeline. One change is one Undo step. |
mute | Video and sound clips. Mutes or unmutes the clip. |
replace | Puts a new file in place of the selected one and keeps its position, size and timing. A video or sound clip uses the Replace file chooser. A picture offers it only when you pass onUploadAsset. |
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: Insert Emoji and Save template. 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 |
|---|---|
ToolRailId | elements, media, photo, video, audio, subtitle, text, brand, shapes, stickers, effects, background, templates, audioEffects, animations, automated |
DockId | media, photo, video, audio, text, brand, elements, shapes, stickers, templates, captions, effects, background, aiChat, resize, automated |
SelectionChipId | editWithAi, makeVideo, rewriteWithAi, crop, clearCrop, mask, clearMask, effects, animations, fitMode, position, fitToCanvas, matchCanvas, removeBg, stabilize, volume, audioFx, captions, generateCaptions, split, speed, fades, opacity, editText, font, fontSize, bold, italic, underline, textColor, textAlign, textStyles, textBackgrounds, fill, stroke, strokeWidth, reRecordPart, viewRecommendations, subtitleStyle, subtitleFontSize, subtitleFont, subtitleTextColor, subtitleBgColor, bgOpacity, subtitlePosition, align, shadow, subtitleAnimation, bringForward, sendBackward, group, ungroup, delete, lock, unlock, trim, mute, replace, copyStyle, pasteStyle |
ToolbarGroupId (old setting) | text, format, style, shapes, images, crop, videos, audio, speed, fades, captions, animations, actions, controls |
Effects, Animations, Audio 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 SelectionChipId 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.