Search Docs
Loading...
Skip to content

Layer & Page List

Configure the layer and page list — which parts of it your users get, where it opens, what it shows, and which commands each row offers.

The CE.SDK design editor with the layer and page list open beside the canvas

8 mins
estimated time
Download
StackBlitz
GitHub

The layer and page list is the panel the dock’s Layers button opens. It shows the document’s pages above the layers of the page being worked on, one row per block, and each row selects, renames, hides, locks and reorders the block it stands for.

This guide covers the three APIs that configure it, each in its own section below:

  • Enable / Disable — the ly.img.layerList.* feature keys decide which parts of the list exist, which sections it shows, and whether picking a row moves the canvas.
  • Opening the List — the Panel API opens, places and floats it; the dock order decides where its button sits.
  • Row Menu — the Component Order API drives the menu on each row, per row kind.

For what the list does once it is on screen — selection, drag-to-reorder, the keyboard — see Layers.

Enable / Disable#

The list is governed by the Feature API. ly.img.layerList is the parent key; its ten children each control one part of the list, so turning one off leaves the rest working.

// Each row control has its own key, so turning one off leaves the rest of
// the list working.
cesdk.feature.disable('ly.img.layerList.lock');
Feature key Controls
ly.img.layerList Parent key: enables all children below
ly.img.layerList.panel The panel
ly.img.layerList.pages The pages section
ly.img.layerList.layers The layers section
ly.img.layerList.combined One tree of every page with its layers, in place of the two sections
ly.img.layerList.canvasFollow Scrolling the canvas to the block a row picks
ly.img.layerList.visibility The hide/show toggle on a row
ly.img.layerList.lock The lock toggle on a row
ly.img.layerList.reorder Dragging a row to reorder it
ly.img.layerList.rename Renaming a row in place
ly.img.layerList.menu The menu on a row

The design and advanced editor configurations enable every key except ly.img.layerList.combined. A configuration lists the keys it wants one by one; enabling the parent key instead turns on every child, combined included, and the list becomes a single tree.

Sections#

Three keys choose what the list shows. With ly.img.layerList.pages and ly.img.layerList.layers enabled, the pages sit above the current page’s layers. Disabling one of the two leaves the other on its own. ly.img.layerList.combined replaces both with a single tree of every page and its layers.

// The pages sit above the current page's layers. `combined` would replace
// both with one tree of every page and its layers.
cesdk.feature.enable('ly.img.layerList.pages');
cesdk.feature.enable('ly.img.layerList.layers');
// cesdk.feature.enable('ly.img.layerList.combined');

Canvas Follow#

ly.img.layerList.canvasFollow decides whether picking a row moves the canvas. Its default predicate follows a page row only, so navigating between pages works while clicking a layer already on screen leaves the canvas alone. cesdk.feature.set('ly.img.layerList.canvasFollow', true) follows every row, and cesdk.feature.disable() follows none. It scrolls rather than zooms, so the zoom level is left where the user put it.

// By default picking a page row scrolls the canvas to it and picking a
// layer row leaves the canvas alone. `true` follows every row; `disable`
// follows none.
cesdk.feature.set('ly.img.layerList.canvasFollow', true);

Opening the List#

The list is a panel like any other, registered under the id //ly.img.panel/layers. Open it with cesdk.ui.openPanel(), close it with cesdk.ui.closePanel(), and read its state with cesdk.ui.isPanelOpen().

// The list is a panel like any other, so the Panel API opens it.
cesdk.ui.openPanel('//ly.img.panel/layers');

It takes the same placement APIs as the inspector and the asset library. cesdk.ui.setPanelPosition() moves it between the two sides, and cesdk.ui.setPanelFloating() decides whether it floats over the canvas or docks beside it. It belongs to no panel group, so an asset library opened over it does not close it.

// Place it beside the canvas rather than floating over it.
cesdk.ui.setPanelPosition('//ly.img.panel/layers', 'left');
cesdk.ui.setPanelFloating('//ly.img.panel/layers', false);

The Dock Button#

The Layers button is an ordinary dock entry: ly.img.assetLibrary.dock with the key ly.img.layerList, no entries, and a click handler that opens and closes the panel. The design and advanced editor configurations end their dock order with a spacer, a separator and that entry, which holds it at the bottom.

{
id: 'ly.img.assetLibrary.dock',
key: 'ly.img.layerList',
icon: '@imgly/Layers',
label: 'component.layerList',
entries: [],
isSelected: () => cesdk.ui.isPanelOpen('//ly.img.panel/layers'),
onClick: () => {
if (cesdk.ui.isPanelOpen('//ly.img.panel/layers')) {
cesdk.ui.closePanel('//ly.img.panel/layers');
} else {
cesdk.ui.openPanel('//ly.img.panel/layers');
}
}
}

The spacer takes the leftover room, so a dock button appended with position: 'end' lands below the Layers button. Pass before: 'ly.img.spacer' to keep your own button up with the asset libraries.

cesdk.ui.insertOrderComponent(
{
in: 'ly.img.dock',
before: 'ly.img.spacer'
},
{ id: 'ly.img.assetLibrary.dock', key: 'my-library', entries: ['my.library'] }
);

An integration that opens the list from its own control removes the built-in button and keeps the panel:

cesdk.ui.removeOrderComponent({
in: 'ly.img.dock',
match: { id: 'ly.img.assetLibrary.dock', key: 'ly.img.layerList' }
});

For the rest of the dock order, see Dock.

Row Menu#

The menu on each row is a Component Order API area identified by ly.img.layerList.menu, gated by the ly.img.layerList.menu feature. A page row and a layer row hold separate orders, selected with the rowKind context. An order read or written without a when clause is the layer row’s.

// Without a `when` clause the layer row order is returned.
const layerMenu = cesdk.ui.getComponentOrder({
in: 'ly.img.layerList.menu'
});
console.log('Default layer row menu:', layerMenu);
const pageMenu = cesdk.ui.getComponentOrder({
in: 'ly.img.layerList.menu',
when: { rowKind: 'page' }
});
console.log('Default page row menu:', pageMenu);

Default Menu Order#

A layer row offers rename, duplicate and delete, then group and ungroup, then the four arrange commands, with separators between the three runs.

A page row offers rename, duplicate and delete, then add page above and add page below. A page has no place in the stacking order and cannot be grouped, so those commands are absent from its menu rather than present and disabled.

Built-in Component IDs#

These IDs are available for a row menu order, alongside any component you register yourself.

Component ID Description
ly.img.separator Visual divider between groups
ly.img.layerList.menu.rename Rename the block in place
ly.img.layerList.menu.duplicate Duplicate the block
ly.img.layerList.menu.delete Delete the block
ly.img.layerList.menu.group Group the selected blocks
ly.img.layerList.menu.ungroup Dissolve the selected group
ly.img.layerList.menu.bringToFront Move in front of every sibling
ly.img.layerList.menu.bringForward Move one step towards the front
ly.img.layerList.menu.sendBackward Move one step towards the back
ly.img.layerList.menu.sendToBack Move behind every sibling
ly.img.layerList.menu.page.addAbove Add a page above this one
ly.img.layerList.menu.page.addBelow Add a page below this one

Trimming the Menu#

cesdk.ui.removeOrderComponent() drops an entry. Here the four arrange commands come out of the layer row’s menu, leaving dragging a row and the bracket shortcuts as the ways to reorder a block.

// Drop the four arrange commands from a layer row's menu. Dragging a row
// and the bracket shortcuts still reorder blocks.
(
[
'ly.img.layerList.menu.bringToFront',
'ly.img.layerList.menu.bringForward',
'ly.img.layerList.menu.sendBackward',
'ly.img.layerList.menu.sendToBack'
] as const
).forEach((match) => {
cesdk.ui.removeOrderComponent({ in: 'ly.img.layerList.menu', match });
});

cesdk.ui.setComponentOrder() replaces an order outright, and cesdk.ui.updateOrderComponent() edits an entry in place — to relabel it, or to disable it under a condition.

Adding Your Own Entry#

A custom entry is a component registered with cesdk.ui.registerComponent() and inserted into the order. Passing when: { rowKind: 'page' } puts it on page rows only.

// A custom entry is a registered component like any other.
cesdk.ui.registerComponent(
'ly.img.layerList.menu.copyName',
({ builder, engine }) => {
const [block] = engine.block.findAllSelected();
builder.Button('ly.img.layerList.menu.copyName', {
label: 'Copy Name',
icon: '@imgly/Copy',
isDisabled: block == null,
onClick: () => {
if (block == null) return;
void navigator.clipboard.writeText(engine.block.getName(block));
}
});
}
);
// Page rows only, so a layer row's menu is left alone.
cesdk.ui.insertOrderComponent(
{
in: 'ly.img.layerList.menu',
when: { rowKind: 'page' },
after: 'ly.img.layerList.menu.delete'
},
'ly.img.layerList.menu.copyName'
);

A command from a row’s menu applies to the whole selection when the row it was opened from is part of that selection, and to that row alone otherwise.

For every matcher and position option these methods accept, see Component Order API.

Troubleshooting#

No Layers button in the dock: the editor configuration has no entry keyed ly.img.layerList in its dock order. Only the design and advanced editor configurations declare one.

A custom dock button sits below the Layers button: it was appended with position: 'end', which lands past the spacer the configuration ends with. Insert it with before: 'ly.img.spacer' instead.

Rows carry no padlock: either ly.img.layerList.lock is disabled, or the active role lacks the ui/fixLayers scope.

The list shows one tree instead of two sections: ly.img.layerList.combined is enabled, most likely because the parent key ly.img.layerList was enabled and cascaded to it. Disable combined, or list the child keys instead of the parent.

A menu change does not reach page rows: the order was set without when: { rowKind: 'page' }, so it applied to layer rows. Page rows read their own order.

API Reference#

Method Purpose
cesdk.feature.enable(id) Enable a layer list feature or the whole family
cesdk.feature.disable(id) Disable a layer list feature
cesdk.feature.set(id, enabled) Replace a feature’s predicate, e.g. follow every row
cesdk.ui.openPanel('//ly.img.panel/layers') Open the list
cesdk.ui.closePanel('//ly.img.panel/layers') Close the list
cesdk.ui.isPanelOpen('//ly.img.panel/layers') Read whether the list is open
cesdk.ui.setPanelPosition(id, position) Place the list on the left or the right
cesdk.ui.setPanelFloating(id, floating) Float the list over the canvas
cesdk.ui.getComponentOrder({ in, when }) Read a row menu order
cesdk.ui.setComponentOrder({ in, when }, order) Replace a row menu order
cesdk.ui.insertOrderComponent({ in, when, before }, c) Insert an entry into a row menu
cesdk.ui.updateOrderComponent({ in, when, match }, update) Edit an entry of a row menu
cesdk.ui.removeOrderComponent({ in, when, match }) Remove an entry from a row menu, or the dock button
cesdk.ui.registerComponent(id, renderFunction) Register a custom row menu entry

Next Steps#

  • Layers - What the list does once it is on screen, and the block APIs behind it
  • Component Order API - Every matcher and option a row menu order accepts
  • Dock - Move, replace, or remove the Layers button
  • Panel - Place and float the list alongside the other panels