Skip to content

Feat/floating nested layout#1310

Open
mathuo wants to merge 9 commits into
masterfrom
feat/floating-nested-layout
Open

Feat/floating nested layout#1310
mathuo wants to merge 9 commits into
masterfrom
feat/floating-nested-layout

Conversation

@mathuo
Copy link
Copy Markdown
Owner

@mathuo mathuo commented May 29, 2026

Description

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactor / cleanup
  • Build / CI / tooling

Affected packages

  • dockview-core
  • dockview (vanilla JS)
  • dockview-react
  • dockview-vue
  • dockview-angular
  • docs

How to test

Checklist

  • yarn lint:fix passes
  • yarn format passes
  • npm run gen has been run and generated files are up to date
  • yarn test passes
  • I have added or updated tests where applicable
  • Breaking changes are documented

mathuo and others added 4 commits May 28, 2026 22:05
Add an optional dedicated grab bar rendered above a floating group's tab
bar that acts as the window move handle (FlexLayout-style). A plain drag
moves the float; shift+drag (mouse) / long-press (touch) redocks into the
grid, reusing the same gesture disambiguation as the tab-bar void handle.

- Overlay gains an optional `header` slot (flex-column layout) + headerHeight
- Extract the redock drag-source machinery (ghost + html5/pointer sources +
  floating disambiguation) out of VoidContainer into a shared GroupDragSource
- New FloatingTitleBar component (contentless; styled via theme vars)
- New option `floatingGroupDragHandle: 'titlebar' | 'tabbar'` (default
  'titlebar') with a per-call `dragHandle` override on FloatingGroupOptions
- floatingGroupService adds the header offset on the group->overlay size path
- Theme vars: --dv-floating-titlebar-{height,background-color,border-bottom}
- Enable it on the docs demo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce the multi-root foundation: a DockviewComponent can host more than one
gridview root (the main grid plus, now, floating windows), all sharing one
groups map, panel registry, DnD transfer namespace and serialization — so there
is still a single public DockviewApi and existing behaviour is unchanged.

- a floating window mounts its own Gridview as the overlay content; the anchor
  group is added into it, and further groups can be split in
- getGridviewForGroup resolves a group's owning root; doAddGroup /
  createGroupAtLocation take a target gridview; moveGroup(OrPanel) compute
  locations against the destination root, so panels/groups can be dragged
  across the main<->floating boundary (and floating<->floating)
- floating groups accept all drop zones (edge drop splits the window);
  doRemoveGroup is multi-group aware (detach one group, keep the window alive)
- serialize/restore each floating window's nested gridview (legacy single-group
  shape preserved for byte-stable round-trips)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the multi-root model to popout windows: a popout hosts its own Gridview
(in the popout document, with its own overlay render + drop-target containers),
so it can hold a nested splitview of groups and participate in cross-boundary
drag-and-drop just like floating windows.

- popout groups accept all drop zones; moveGroup(OrPanel) and doRemoveGroup are
  popout-root aware (split into a popout, drag in/out, multi-group windows)
- getOverrideTarget resolves dynamically so a relocated group's drop overlay
  mounts in the correct window
- serialize/restore the popout's nested gridview (legacy single-group shape
  preserved); restore rebuilds it via an internal override
- size + reposition the popout via a ResizeObserver created in the popout
  window's own realm, so content lays out at the real size once the window has
  painted (a parent-realm observer / fixed animation-frame count raced)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Harden the restore path against real-world popout edge cases surfaced by
loading saved layouts:

- when the browser blocks a popout window (window.open returns null — common
  when restoring on load), dock the group into the grid (or return its panels
  and dispose the empty group) instead of leaving an orphan; blocked content
  falls back into the grid rather than being lost
- dispose 'grid'-location groups whose element isn't actually in the gridview
  (a popout-destined group swept up by a re-entrant fromJSON / clear) instead
  of throwing "Invalid grid element"

Adds regression tests for blocked-popup restoration and rapid repeated fromJSON.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mathuo mathuo changed the base branch from master to feat/modules May 29, 2026 21:20
mathuo and others added 3 commits May 29, 2026 22:26
…outs

In spaced themes the floating border + rounded corners are applied to the group
(.dv-groupview) rather than the outer resize container. With the dedicated
drag-handle bar now sitting above the group, that left the handle with a square,
border-less top while the group below it kept the rounded top — so the card
looked wrong. Move the top border and rounded top corners onto the drag handle
(it's now the top of the card) and flatten the group's top so the two read as a
single rounded card.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When a floating window has a dedicated title-bar move handle, the tab bar's
void container is no longer the move handle, so it no longer needs the shift
(mouse) / long-press (touch) gate that disambiguated it from moving the float.
It now initiates a group drag with a plain drag, exactly like a group in the
main grid. The gate still applies to whichever element actually moves the float
(the title bar, or the void container itself in the legacy tab-bar mode).

GroupDragSource gains an `isFloatingMoveHandle` predicate; the void container
reports false when its overlay is `.dv-resize-container-with-titlebar`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mathuo mathuo changed the base branch from feat/modules to master May 30, 2026 21:02
mathuo and others added 2 commits May 30, 2026 22:33
Three fixes from reviewing the nested floating/popout layout work:

1. The dedicated floating title bar (default floatingGroupDragHandle:
   'titlebar') captured its anchor group permanently, so after the
   original anchor was dragged out of a surviving multi-group window the
   bar still redocked/activated the departed group. GroupDragSource.group
   now accepts a provider resolved lazily; FloatingTitleBar holds a
   mutable anchor with setGroup(); DockviewFloatingGroupPanel.setAnchorGroup
   retargets it; onWillDragGroup fires the live anchor.

2. Nested floating/popout gridview gap was not updated on runtime theme
   change; updateTheme now syncs .margin on every nested gridview.

3. Multi-group popout restore while popups are blocked orphaned the
   non-anchor members; the blocked fallback now docks every member into
   the main grid.

Adds regression tests for (1) and (3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant