Documentation
More

Known limitations

What is not there yet, the workaround the examples use, and the Epic that removes it.

Dockable is young. This page lists, honestly, what the public surface is missing today. The numbered gaps come from the project's walking-skeleton report (section 2), with the same numbers, so issues and example comments can refer to them ("gap 10"). Each has the workaround the examples use and the Epic that will remove it, when one is scheduled.

The gaps

#missingworkaround (what the examples do)removed by
1Tab knows selected but not whether its tabset is active, so "the selected tab of the active tabset" has no attribute.An ancestor selector: .tabset[data-active] .tab[data-selected], or Tailwind's in-data-active: / group-data-active: on a child of the tab.not scheduled yet
2Panels live outside their tabset (in the panel layer), so a tabset's border-radius/overflow cannot clip them, and a panel cannot be styled by its tabset's state.Rounded tabsets repeat the tabset's inner radius on the panel's bottom corners (it breaks if the strip moves to the bottom), or use square tabsets. The active tabset is marked on its selected tab instead of with a tabset-wide ring.not scheduled yet
3A popout document does not get the page's root attributes and body classes. Solved: popoutMirrorRoot on Root mirrors <html> and <body> attributes. See Popouts.None needed.Epic #20 (done)
4Flipping dir at runtime leaves the panels at their old positions. Solved: the engine observes dir attributes and repositions the panels. See Right-to-left layouts.None needed.Epic #112 (done)
5In RTL, splitter drags, keyboard resizing and drops are wrong. Solved: the engine reads the root's direction, so splitters, arrow keys, side, edge and strip drops and overlay borders follow the screen, with start on the right. See Right-to-left layouts.None needed.Epic #112 (done)
6Styling every splitter the same way needs renderSplitter on every Row (root, nested, and inside Popout).Pass renderSplitter to every Row (the examples write one Splitter component and pass it in their recursion), or style [role="separator"] from a stylesheet.not scheduled yet
7A pop out button for a tabset's selected tab has no primitive. Solved: Dockable.PopoutTrigger. See Popouts.None needed.Epic #20 (done)
8No drop-target state on the tabset under the pointer. Solved: data-drop-target and data-drop-location on TabSet, data-drop-target and data-drop-index on TabList. See Drop zones and drop feedback.None needed.Epic #19 (done)
9No way to make a splitter's hit area wider than its visible thickness.A 1px splitter with a centred ::after grab area, relative z-10; the engine measures the 1px element, so the split maths is exact. See Splitters.not scheduled yet
10A drop before the first tab is refused when that tab is flush with the tabset's edge. Solved: a tab flush with the tabset's edge takes a drop before it; only a tab scrolled out of the strip refuses one.None needed.Epic #112 (done)
11A thin tab strip at the top of the layout falls inside the 10px top-edge docking band. Solved: the band is the layout default defaults.layout.edgeDockMargin (lower it for a thin strip), and Dockable.EdgeIndicator shows the bands during a drag. See Borders.Keep strips about 30px tall, or set defaults.layout.edgeDockMargin.Epic #21 (done)
12The drop indicator paints under the panels: panels are portalled into the root after its other children.A z-index on the indicator (z-10).not scheduled yet

Features not built yet

featurestatusremoved by
Floats (in-page floating windows)not built: a tab leaves the main layout only into a popout windownot scheduled yet
Tab groups (pills grouping tabs in a strip)not built: a tabset or border holds tabs onlynot scheduled yet
Border extras: a pop out button in a border's stripnot rendered; a border's strip is yours to fill (Dockable.PopoutTrigger works in tabsets only)not scheduled yet
Fill and fixed sizes (a tabset that takes the remaining space, a size in pixels)not built: rows share their space by weight, within each node's minWidth/maxWidth/minHeight/maxHeightnot scheduled yet
Cross-window tab drag (a tab dragged to another browser tab or window of the app)not built: a drag crosses the layouts and popouts of one page, not separate pagesnot scheduled yet
Several open tabs per bordernot built: a border shows one selected tab at a timenot scheduled yet
A popout document hook for libraries that portal into the global documentnot built: give such a library the content's ownerDocument yourself (Popouts)not scheduled yet
Inline rename on F2the renameTab binding exists in the key map but the primitives do not act on it; build the rename UI, which asks model.can("tab.rename", …) and runs tab.rename with the new label (Tabs)not scheduled yet
Adapters for Angular and Vuethe core is framework-agnostic so they can follownot scheduled yet

RTL

Right-to-left layouts render and respond with start on the right: see Right-to-left layouts. A direction set by CSS alone (no dir attribute) is the one change the engine does not see: run engine.run("measure-and-position") after it.

Popout edge cases

  • Closing a popout runs window.close, which docks its tabs back into the main layout. A middleware that vetoes it keeps the window layout in the state with its window gone: the engine tries to open it again, and if the browser blocks that, its tabs are unreachable until the layout is loaded again. Do not veto window.close.
  • The browser may block a popout that is reopened without a user gesture (for example when a saved layout with windows is restored at start-up).

Other things to know

  • The root needs a size (by design): an unsized root renders nothing visible. See Sizing the root.
  • A bottom tab strip is a markup change (render TabSetContent before the TabList), not a style: TabSet is a structural flex column.

Found while writing the examples

The examples hit one more rough edge. It is worked around (and commented) in the example named, and listed in docs/docs-examples-gaps.md in the repository.

  • An input inside a tab gets the tab's keyboard handling and dragging: stop key propagation and set draggable={false} while editing. See rename-tabs.

Found something else?

Open an issue. A gap you work around in your app is exactly what the next Epics need to hear about.