Skip to content

Feature: Container Panel - #751

Open
H3mul wants to merge 7 commits into
0-AI-UG:mainfrom
H3mul:pr-feat-container-panel
Open

H3mul wants to merge 7 commits into
0-AI-UG:mainfrom
H3mul:pr-feat-container-panel

Conversation

@H3mul

@H3mul H3mul commented Oct 4, 2026

Copy link
Copy Markdown

Hey! I've been integrating Cate into my everyday workflows, and found myself missing this important feature.

I often use terminal splits for specialized cases (eg something where I must interact with a process and introspect logs at the same time), but also need to switch away to other workflows. I started using Canvases for this, but I found myself spending more time placing them in the viewport than seamlessly interacting with them.

I propose a new panel: a Container, which encapsulates a window split just like the host window does currently but as a separate modular panel type.

  • Create a new container from the panel creation menu, or by making a new split
  • Drag tabs into it / out of it
  • A container can't contain a container currently (seemed redundant)
  • A container can contain a canvas and vice versa
Screenshot 2026-10-04 100602 Screenshot 2026-10-04 100617 Screenshot 2026-10-04 100541 Screenshot 2026-10-04 100632

Let me know what you think!
I have a few more ideas to integrate which I'll introduce in future PRs that are related.
My next gripe is panel reorganization: I'd like to be able to drag panel tokens both in headings and in the sidebar to reorganize both order and Canvas/Container membership

H3mul added 7 commits October 4, 2026 10:11
A container is a panel that hosts its own split/tab tree, like a canvas
node's mini-dock promoted to a first-class panel. It owns a private
DockStore and mirrors its layout into PanelState.containerLayout so the
layout persists with the panel record.

- canContain()/excludedChildTypes() in shared/panels.ts are the single
  source of truth for what a dock, canvas or container can host (a
  container hosts anything but a container; a canvas anything but a
  canvas). CanvasNode now derives its exclusions from it.
- New containers start empty and stay open when their last panel leaves.
- Children's records are persisted with the container and torn down
  when it closes.
resolvePanelLocation gains a 'container' kind, found via the container's
mirrored layout. Reveal-by-id now reveals the container wherever it is
placed (dock, canvas, or another container) and selects the child's tab;
closePanel removes a child from its container's layout. Moving a
container-hosted panel to a new window is declined for now.
- Route the canvas-drop guards (same-window, cross-window, drop preview)
  through canContain, and refuse a container that holds a canvas on a
  canvas or canvas-node mini-dock (canvas -> container -> canvas).
- Dragging a panel onto the edge of a window-level stack no longer makes
  a window split: the panel under the cursor is wrapped in a container
  and the split happens inside it. If that panel is already a container,
  the split lands inside it at the edge of its whole layout.
- resolve/commit take the app-store lookups by injection so they stay
  free of the heavy store graph.
Containers are grouping parents like canvases: their children nest under
them, and a container on a canvas (or a canvas inside a container) nests
under its owner. The Cmd+K palette order and the cross-window panel
report follow the same ownership.
registerContainerDockStore ran only inside useMemo, but the unregister ran in
an effect cleanup. Under StrictMode's mount -> cleanup -> mount, the cleanup
removed the store and nothing re-registered it, so an open container looked
unmounted to getContainerDockStore.

Callers then fell back to writing the mirrored containerLayout, which the live
DockStore never re-reads (it only seeds from it once). Visible symptom: picking
a container child in the sidebar didn't switch the container's active tab
unless the container had been unmounted first.

Register in the effect as well, so the registration matches the cleanup.
Container panes now use the same compact mini heading as canvas windows
(22px pills, chromeless 26px strip) instead of the full-size header band.
@Anton-Horn

Copy link
Copy Markdown
Contributor

Hey, thanks a lot for this! The use case makes a lot of sense. I run into the same thing with splits I want to keep around but switch away from.

I'm not sure a separate panel type is the right shape for it though. A container is basically a second docking system inside a panel, so it ends up touching drag and drop, closing, the sidebar, restore and window transfer. It also needs its own nesting rules.

What I'd like to try instead is multiple layouts per window. Each window keeps a list of dock trees, one is active, and you switch between them with a small switcher plus shortcuts (kind of like tmux windows). It covers the same thing, a split you can tab away from and come back to, but everything stays flat and every panel still lives in exactly one dock.

Also, #744 is about to change a lot here. Panels, windows and dock trees now live in a document on the runtime side, and the src/renderer code this PR is built on is mostly gone. With that model, layouts are mostly a schema change on the window plus a switcher in the UI.

Would be great if you could base it on the architecture PR (#744 / refactor/runtime-architecture). docs/architecture.md explains how the document and docks fit together. Happy to help or talk through the details if you want to take it on!

@Anton-Horn

Copy link
Copy Markdown
Contributor

I was busy the last few days. Will be more active for the rest of the week and continue to work on the architecture rework. Happy to review your other idea's, work on them with you together!

@H3mul

H3mul commented Oct 7, 2026 •

Copy link
Copy Markdown
Author

That's a good point. I wanted recursive compositing just for the purpose of being able to drag a full split panel into Canvas if I wanted to - but after about a week of testing I never used this lol. If the use-case comes up, we should be able to convert the panel split tree directly into a canvas node and back again rather than introducing a new host dock.

I like the goal of making the panel dock architecture with singular ownership, and I am a big fan of tmux myself. Let me see what I can come up with that fits this pivot

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.

2 participants