Layout historyEnterprise
Dockview can keep a bounded undo/redo stack of layout mutations, giving you
Ctrl+Z for your layout. Closing a panel by accident, dragging a group to the
wrong split, floating something, maximizing or a fat-fingered resize can all be
reverted with api.undo() and re-applied with api.redo().
The feature is off by default and records nothing until you opt in.
Enabling
Turn history on by setting the layoutHistory option with { enabled: true }.
The option is honoured live, so you can toggle it at runtime via
updateOptions.
clearOnFromJSON | Clear the stacks when the whole layout is replaced via fromJSON /
clear. Default true.
|
|---|---|
coalesceMs | Debounce window (ms) for coalescing a continuous resize drag into one
undo entry. Default 400.
|
depth | Max undo depth (bounded ring). Default 25.
|
enabled | Record mutations. Default false (module is registered but inert).
|
recordResize | Record sash-resize as undoable steps, coalescing a continuous drag into
a single entry. Default true.
|
undoableProgrammaticMutations | Also record mutations originating from DockviewApi calls (the app's
own programmatic changes). Default false; only user gestures.
|
What gets recorded
Each undoable step is a full snapshot of the layout captured before and after
the mutation, so an undo restores the whole layout, including a closed panel's
params and title.
The following structural mutations each record one undo step:
add/remove: adding and closing panels or groupsmove: dragging or moving a panel or group to a new locationfloat: floating a grouppopout: opening a group in a popout windowmaximize: maximizing / restoring a grouptab-group: tab-group changes (such as recolouring)
Resize (dragging a sash) has no discrete mutation boundary, so it is caught
separately and a continuous drag is coalesced into a single entry. It is
recorded by default; set recordResize: false to ignore resizes, and tune the
debounce window with coalesceMs (default 400ms).
A panel's state is only restorable on undo if it is serialized into the panel's
params. State held imperatively outside params (for example a chart's zoom
kept in a closure) is not captured by the snapshot; this is the same constraint
that fromJSON already imposes.
History depth
The stack is a bounded ring. depth (default 25) caps how many undo steps are
retained; pushing past the limit drops the oldest entry.
User vs programmatic mutations
By default only user gestures (drag-dock, tab close button, sash resize)
enter the stack. A programmatic DockviewApi call such as api.addPanel(...)
is treated as the app's own state management and is not something the end user
expects Ctrl+Z to revert. Set undoableProgrammaticMutations: true to record
those too.
Clearing on a full restore
Loading a whole new layout via fromJSON (or calling
api.clear()) clears the history by default, so undo can't resurrect a layout
from a different session. Set clearOnFromJSON: false to keep the stacks across
a full restore.
Driving undo / redo
Dockview binds no keyboard shortcuts itself; wiring Ctrl+Z / Ctrl+Shift+Z
(or toolbar buttons) to api.undo() / api.redo() is the host app's call. Use
canUndo / canRedo to drive the disabled state of your controls, and listen
to onDidChangeHistory to keep them in sync as the stacks change.
canRedo | Whether redo would do something.
|
|---|---|
canUndo | Whether undo would do something. Reactive via onDidChangeHistory.
|
onDidChangeHistory | Fires whenever the undo/redo stacks change.
|
clearHistory | Drop both undo and redo stacks (e.g. on document switch).
|
redo | Re-apply the next layout mutation undone via undo.
|
undo | Undo the previous recorded layout mutation. No-op when there is nothing
to undo, when layoutHistory.enabled is not set, or when the
LayoutHistory module is absent.
|
onDidChangeHistory fires whenever the undo/redo stacks change (on every push,
undo, redo and clear) and carries the reactive state:
canRedo |
|
|---|---|
canUndo |
|
lastEntry |
|
redoCount |
|
undoCount |
|
Cross-window support
Undo and redo restore the whole layout, including floating groups and popout windows. A mutation made inside a popout window is still a mutation of the same dock and records a single step on the shared stack.
Floating groups restore synchronously, but popout windows re-open
asynchronously. If an undo or redo re-opens a closed popout, await
api.popoutRestorationPromise to know the window is ready.
Browsers only allow window.open from within a user gesture. An undo re-opening
a popout must originate from a trusted user event (a keyboard shortcut or a
button click); otherwise the popout falls back to an inline group.
See also
- Saving state: persist a layout snapshot with
toJSON. - Loading state: restore a serialized layout with
fromJSON.