For the complete documentation index, see llms.txt. This page is also available as Markdown.

Canvas UI reference

Technical reference for the CanvasLayout component and its APIs.

This page is intended for developers who need to understand or extend the Canvas UI component.

Component location

assets/src/App/components/CanvasLayout/
├── index.jsx            # Main CanvasLayout component
├── CanvasUIPreferences.jsx  # Toolbar preference toggles
└── CanvasPreviewItem.jsx    # Drag-overlay preview element

CanvasLayout props

Prop
Type
Required
Description

sensors

object

Yes

@dnd-kit sensor configuration (pointer + keyboard).

onDragEnd

function

Yes

Called with the drag result when an item is dropped.

collisionDetection

function

No

@dnd-kit collision-detection strategy used to determine valid drop targets. Defaults to rectIntersection; pointerWithin is also available for contexts that need more precise pointer-based targeting.

sidebar

ReactNode

Yes

Content rendered in the sidebar panel (left by default; see Sidebar position).

canvas

ReactNode

Yes

Content rendered in the canvas panel.

dragOverlay

ReactNode

Yes

Element rendered as the drag ghost.

id

string

No

Unique identifier for this canvas instance.

preferenceId

string

No

Raw entity ID used as the localStorage key for layout preferences. Defaults to id.

wrapperRef

ref

No

Ref attached to the outer wrapper element.

toolbarRef

ref

No

Ref attached to the toolbar element.

extraOptions

array

No

Additional toolbar toggle options (see below).

sidebarDefaultSize

number

No

Default sidebar width as a percentage (default: 450px-equivalent).

sidebarMinSize

number

No

Minimum sidebar width in pixels (default: 400).

sidebarMaxSize

number

No

Maximum sidebar width in pixels (default: 700).

extraOptions shape

The No-distraction toggle is always present and does not need to be included in extraOptions.

useUIPreference hook

Each toggle in the toolbar is backed by the useUIPreference hook, which reads and writes to localStorage:

The hook returns [value, setter] — identical signature to useState.

Drag-and-drop internals

CanvasLayout wraps its children in a @dnd-kit DndContext. Each draggable item must use useSortable from @dnd-kit/sortable:

The onDragEnd prop receives the standard @dnd-kit drag-end event. Use arrayMove from @dnd-kit/sortable to reorder the item array:

Click-to-add activation distance

Sidebar items can be added to the canvas either by dragging or by a plain click. A pointer-sensor activation-distance threshold (a few pixels of movement) is what allows this: it distinguishes a click from the start of a drag, so a click fires the "add" handler instead of starting a drag operation. Consumers wiring up their own sidebar items should apply the same activation-distance constraint on their MouseSensor if they want click-to-add alongside drag-to-add.

A SidebarPositionButton toggle pair (in CanvasUIPreferences.jsx) lets the user dock the sidebar on the left or right of the canvas. Like the other toolbar toggles, the choice is persisted via the useUIPreference hook, keyed off preferenceId, so it's remembered per entity.

Inline editing (nameSlot)

CanvasPreviewItem exposes a nameSlot render prop so consumers can inject inline-editable controls into the card header instead of relying solely on the settings panel. Known consumers include the form builder's inline Label editor, and equivalent inline name/type editors for meta fields, dynamic blocks, and CCT table columns — each lives alongside its own page (not inside the shared CanvasLayout/ directory above).

A field/column-level isReusable flag governs two things: whether its name is inline-editable at all, and whether it can be re-added to the canvas while already present. It's false for items bound to an existing meta field, CCT column, or WordPress core field, so that binding can't be broken by a rename or duplicate.

Resizable panels

The sidebar/canvas split uses react-resizable-panels. The divider position is persisted in localStorage under the key acpt_canvas_panel_{preferenceId}. The sidebar Panel also has an explicit, stable id, which fixes a bug where saved panel widths could get mixed up after switching the sidebar from one side to the other.

Dependencies

Package
Version
Role

@dnd-kit/core

6.x

Drag-and-drop context

@dnd-kit/sortable

7.x

Sortable list abstraction

@dnd-kit/utilities

3.x

CSS transform helpers

react-resizable-panels

4.x

Resizable sidebar/canvas split

Last updated