Dockable
API reference

Dockable.Root

The layout's root - owns the engine for a model and is the containing block the panels are positioned in.

"The layout's root: owns the engine for model, attaches it to the rendered element (the containing block the panels are positioned in), runs the measure-and-position cycle after every commit and re-renders when the engine asks."

<Dockable.Root model={model} onAction={onAction} getLabel={getLabel} className="layout">
    <Dockable.Row>{renderNode}</Dockable.Row>
    <Dockable.Panels>{(tab) => <Dockable.Panel node={tab}>{content(tab)}</Dockable.Panel>}</Dockable.Panels>
    <Dockable.DropIndicator />
    <Dockable.Popout>{() => <Dockable.Row>{renderNode}</Dockable.Row>}</Dockable.Popout>
</Dockable.Root>

The root has no intrinsic size; give it one (Sizing the root).

Props

RootProps extends the common primitive props.

proptypedefaultdescription
modelModelrequiredthe layout model; a new model identity (e.g. an undo/redo swap) creates a new engine
onAction(action: Action) => Action | undefinednoneintercepts every action: return it (or a replacement) to apply it, undefined to veto
onModelChange(model: Model, action: Action) => voidnonecalled after the model applied an action
getLabelGetLabelnoneresolves label keys to text (accessible names); with no resolver the primitives render no text of their own
keyMapIKeyMapdefaultKeyMapkeyboard bindings, merged over defaultKeyMap
realtimeResizebooleantruetrue (default) to resize live while dragging a splitter; false to preview and commit on release
tabDragSpeednumber0.3seconds a view may take to animate the drop indicator (exposed as data; default 0.3)
popoutURLstring"popout.html"the popout host page (default "popout.html"); the window layout's id is passed as ?id=
supportsPopoutbooleana desktop pointer is presentwhether window layouts open as popouts; default: a desktop pointer is present
popoutClosePolicy"dock" | "float""dock"what closing a popout window does; default "dock" (its tabs move back to the main layout)
onPopoutOpen(layout: ModelLayout, window: Window, document: Document) => voidnonea popout document is ready, before its content renders
onPopoutClose(layout: ModelLayout, window: Window, document: Document) => voidnonea popout window is closing
popoutMirrorRootboolean | readonly string[]none (only lang and dir)copies the main document's <html> and <body> attributes into each popout and keeps them in sync (a theme class, data-theme, …): true copies them all (except style and id), a list copies those names
onExternalDrag(event: DragEvent) => { json: IJsonTabNode; onDrop?: (node, event) => void } | undefinednoneaccepts a drag that did not start in a layout (files, links, text, another library's element) as a new tab: return { json, onDrop? }, or undefined to ignore it. Called when the drag enters the layout (once per entry), when only event.dataTransfer.types is readable; read the data in onDrop. See External drag
onAllowDrop(dragNode: Node, dropInfo: DropInfo) => booleannonedecides whether a drag may drop at a target: return false to refuse it (the outline hides, the target gets data-drop-refused). The same rule as model.setOnAllowDrop, which it sets while given; removing the prop restores the model's own rule
childrenReactNodenonethe layout: a Row, Panels, DropIndicator, Popout, and anything else

GetLabel is (key: DockableLabel, ...args: (string | number)[]) => string | undefined; see Labels. IKeyMap is described in Keyboard.

State

RootState, passed to render, className and style functions.

fieldtypedescription
maximizedbooleana tabset of the main layout is maximized
draggingbooleana node of this layout is being dragged
refusedbooleanthe drag is over a target of the main layout that a drop rule refused

Data attributes

attributewhen
data-layout-pathalways "/layout"
data-maximizeda tabset of the main layout is maximized
data-dragginga node of this layout is being dragged
data-drop-refusedthe drag is over a target that a drop rule refused

Structural style

position: relative: the containing block the panels (and the root row) are positioned in.

Behaviour

  • Creates one engine per model identity and attaches it to the element on mount.
  • After every commit, runs engine.sync() (measure, then position the panels).
  • Listens on its document for the focusNextTabset/focusPreviousTabset bindings.
  • Provides the context useDockable reads.

Common props

Every primitive except Panels accepts these on top of its own props (PrimitiveProps and the div attributes, as DivPrimitiveProps<State>):

proptypedescription
renderReactElement | (props, state) => ReactElementreplaces the rendered element (never asChild)
classNamestring | (state) => string | undefineda class name, or a function of the primitive's state returning one
styleCSSProperties | (state) => CSSProperties | undefineda style, or a function of the primitive's state returning one. Structural keys the primitive sets (position, geometry, display, flex sizing) always win
refRef<HTMLElement>merged with the primitive's own ref
any div attributeforwarded to the element; event handlers run after the primitive's own

The exported types are PrimitiveProps<State>, DivPrimitiveProps<State>, RenderProp<State> and RenderedProps (the props a render function receives: spread them onto the element it returns). See The primitive contract.

On this page