Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
95e47f8
Add gui.add_panel for floating side-by-side control panels
ArthurAllshire May 5, 2026
6c79a79
Merge branch 'main' into add-panel-api
ArthurAllshire May 5, 2026
6e647f2
Regenerate handle docs to include GuiPanelHandle
ArthurAllshire May 5, 2026
885708d
Merge branch 'main' into add-panel-api
ArthurAllshire May 20, 2026
0427afb
Fix skinned mesh playback loop refs (#729)
abcamiletto Jun 22, 2026
7814151
Fix type error from stub change to `np.cross()` (#732)
brentyi Jun 23, 2026
3bcaf9f
Rebase, support adding tabs to panels
brentyi Jun 23, 2026
6844b50
Merge branch 'main' of github.com:nerfstudio-project/viser into add-p…
brentyi Jun 23, 2026
c63e2b7
Panels: dedicated entity, placement/sizing fixes, dock hardening
brentyi Jun 23, 2026
9b3a313
Tests: single floatingWindow() factory for dock windows
brentyi Jun 23, 2026
5513e74
Dock: WindowHeight tagged union (auto | pinned)
brentyi Jun 23, 2026
4588e0e
Dock: float ownership as a single `anchor` object
brentyi Jun 23, 2026
ee48514
Dock: fix invariant false-positive on empty area groups; avoid height…
brentyi Jun 23, 2026
236b972
Dock: cap rendered region widths so docked panels never occlude the c…
brentyi Jun 23, 2026
0e93a61
Dock: structural-audit follow-ups (simplicity + correct-by-construction)
brentyi Jun 24, 2026
aa63d77
Dock: reuse the floating window when re-placing an already-floated panel
brentyi Jun 24, 2026
c8fb43a
Dock: set_width/set_height take effect on an already-docked panel
brentyi Jun 24, 2026
1b59512
Dock: long tab/header labels show an ellipsis instead of hard-clipping
brentyi Jun 24, 2026
35ad0b8
Dock: better minimized-panel UX (per-tab strip, click-to-expand, grab…
brentyi Jun 24, 2026
d48dadb
Dock: one clamped grabOffset helper for all tear-out drag starts
brentyi Jun 24, 2026
218afd9
tests/e2e: stop vite dev server from watching .nodeenv/node_modules
brentyi Jun 24, 2026
5852233
Panels: `with panel:` raises the helpful TypeError, not bare Attribut…
brentyi Jun 24, 2026
4481be9
Dock: make minimized-strip tab rows keyboard-accessible
brentyi Jun 24, 2026
caa3dba
Dock: undocking a minimized panel keeps its width (not the strip's)
brentyi Jun 24, 2026
361d5e0
Dock: drop on a tab strip beats the region-edge band it overlaps
brentyi Jun 24, 2026
30d7284
Dock: drop the distracting active-tab highlight in the minimized strip
brentyi Jun 24, 2026
dc2ee47
Dock: stable single drop hint across a stacked-panel seam
brentyi Jun 24, 2026
f6bf3b0
Dock: tapping any panel handle toggles minimize (was main-panel-only)
brentyi Jun 24, 2026
d9c6944
Dock: remove the fixed max panel width (was inconsistently applied)
brentyi Jun 24, 2026
d51bd4f
Dock /simplify: finish max-width removal + dedup keyboard/clamp/bounds
brentyi Jun 24, 2026
327a11e
Dock: floor floating-window set_width at the grab minimum
brentyi Jun 24, 2026
ea3f08a
Dock: size-only re-placement no longer re-docks a user-moved panel
brentyi Jun 24, 2026
be6a7dd
Dock: re-populating an emptied docked panel re-shows it
brentyi Jun 24, 2026
f219bba
Dock: minimized strip scrolls when rows overflow; caps long labels
brentyi Jun 25, 2026
5277f09
Docs: dock_above/dock_below/main_panel note the anchor must be docked
brentyi Jun 25, 2026
f98c739
Dock: factor the top-level pure-column shell (SplitView)
brentyi Jun 25, 2026
1b80b13
Dock: harden the sync layer + invariant checker
brentyi Jun 25, 2026
b220b1d
Dock: tearOutPane no-ops when the pane isn't in the group (+ fuzz areas)
brentyi Jun 25, 2026
8f8f384
Dock fuzz: also exercise floatColumn (covers stackWeights invariant)
brentyi Jun 25, 2026
6dbbe57
Dock: rescale a minimized column cell's weight on a sibling resize
brentyi Jun 25, 2026
460f5f1
Dock: resize the 3D canvas synchronously during a region-width drag
brentyi Jun 25, 2026
d2aab11
Dock: instant canvas resize + push floats only out of a growing regio…
brentyi Jun 26, 2026
7173741
Dock: hide the panel header's bottom rule when minimized
brentyi Jun 26, 2026
26d4783
Dock /simplify: drop stale comment + unneeded containerHeightRef
brentyi Jun 26, 2026
999db54
Dock /simplify: remove redundant state + dead code (panel logic)
brentyi Jun 26, 2026
992c039
Dock tests: port a seam-equivalence e2e assertion to vitest
brentyi Jun 26, 2026
db7f146
Dock: keep unanchored floats clear of docked chrome on inset change
brentyi Jun 26, 2026
3196093
ControlPanel: remove the scene tree's nested horizontal scrollbar
brentyi Jun 26, 2026
1dcfc7e
e2e: drop 3 dock tests that duplicate vitest coverage
brentyi Jun 26, 2026
dce1fed
Dock: shrink the panel minimize/expand +/- icons (14 -> 12)
brentyi Jun 26, 2026
23771a8
Example (11_panels): start all panels minimized (expand_by_default=Fa…
brentyi Jun 26, 2026
874810c
Dock: add whitespace between the + handle and labels in the minimized…
brentyi Jun 26, 2026
4b2a7ae
Panels: write-only per-axis placement + minimize(); main panel label/…
brentyi Jun 26, 2026
3e307da
Dock: outer-edge dock past a minimized strip, single-tab tear-out, ve…
brentyi Jun 26, 2026
11d193e
Remove viser logo icon from minimized control panel
brentyi Jun 26, 2026
61755d1
Make minimized-stack parent + handle consistent and draggable
brentyi Jun 26, 2026
15c7d8b
Make minimized panels full drop targets; drag never expands
brentyi Jun 26, 2026
80b2f62
Fix minimized-strip drop/render bugs (tear-out, hint, tall rect)
brentyi Jun 26, 2026
4fb8601
Stack-level minimize: a 2+ stack is all-minimized or all-expanded
brentyi Jun 26, 2026
3e6e8a1
Don't flood a minimized strip with the split-preview tint
brentyi Jun 26, 2026
f189e13
Simplify: dedup minimize/collapse helpers, read collapse from model
brentyi Jun 26, 2026
0cedc3d
Minimized stacked cells: grip bar instead of a + cap
brentyi Jun 26, 2026
f4c4a9d
Docked header top rule + subtler minimized grip pill
brentyi Jun 26, 2026
78598d8
Docked header top rule: only when stacked, matching gray
brentyi Jun 26, 2026
a26b416
Header top rule: show whenever stacked (docked or floating)
brentyi Jun 26, 2026
ff4625a
Fix floating stack cells collapsing under their headers
brentyi Jun 26, 2026
bc31727
Undock a minimized column at its expanded width, not the strip width
brentyi Jun 26, 2026
b0fe8df
Simplify: share the minimized-float-width rule across drag handlers
brentyi Jun 26, 2026
ebbd54c
Floating window height: content is a floor, not a ceiling (+ snap det…
brentyi Jun 27, 2026
d9ade60
Simplify: one contentReachable predicate for the resize detent
brentyi Jun 27, 2026
57c7600
Fix revert-to-auto detent firing far from the content height
brentyi Jun 27, 2026
210d1a3
Reduce minimum panel heights to 50px
brentyi Jun 27, 2026
343a4ff
Animate the docked region width on minimize/expand
brentyi Jun 27, 2026
b422d68
Dock-beside zone for a sole minimized docked strip
brentyi Jun 27, 2026
8dbddd4
Revert "Animate the docked region width on minimize/expand"
brentyi Jun 27, 2026
84348d6
Full-height dock-beside on BOTH edges of a sole minimized strip
brentyi Jun 27, 2026
a2e316b
Server: per-panel layout-update counter on placement messages
brentyi Jun 28, 2026
b8bb106
Client: keep user-rearranged panel layout across reconnect
brentyi Jun 28, 2026
5367223
Fix two stale panel e2e tests for the current minimize model
brentyi Jun 28, 2026
f2620cb
Add "Reset Panel Layout" to Dev Settings
brentyi Jun 28, 2026
41b618b
Simplify layout-persistence: dedup, reuse, fix programmatic flagging
brentyi Jun 28, 2026
b232acd
Prune layout tracking for removed panels (code-review fix)
brentyi Jun 28, 2026
ae6c743
Main-panel header: click-to-minimize only when lone, not stacked
brentyi Jun 29, 2026
40bcfbb
Animate docked minimize/expand (per-cell flex + lone-region width)
brentyi Jun 29, 2026
e9a507f
Simplify minimize-animation gating + share the duration constant
brentyi Jun 29, 2026
424291d
Fix two review-found layout-tracking edge cases
brentyi Jun 29, 2026
0473a8a
Apply ruff format to _gui_handles.py
brentyi Jun 29, 2026
96d59fb
Stabilize disconnect-dim e2e under parallel load + ruff-format tests
brentyi Jun 29, 2026
555df3c
Merge branch 'main' into add-panel-api
brentyi Jun 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ test-results/
# Scene verification outputs
scene_verification_outputs/
tests/e2e/test_webgl_warning.py
.venv/
74 changes: 74 additions & 0 deletions design/dock-correct-by-construction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Dock layout: correct-by-construction program

Status: in progress. From a multi-agent architecture study of the recurring
bug classes this session uncovered (duplicate panes, stale anchors, height
pin-trap, scattered-tab gather, the requestedX/Y re-resolve dance, the
three-effect `visible` coordination). The goal is to make those bug *classes*
unrepresentable / caught-at-commit, not just fixed case by case.

The studies' consistent verdict: the leverage is in a few targeted structural
changes plus a verification net -- NOT big renormalizations. Two options were
explicitly rejected: a normalized `paneLocation` index (moves the invariant into
an order+index pair that can still desync; triples serialization surface; tab
order is load-bearing so duplicates still aren't truly unrepresentable) and a
client-side command-log/seq-cursor (the wire is already a coalesced last-write-
wins snapshot, so a log would re-derive what the server already collapsed).

## Done

- **#1 Invariant checker in production + dev assert.** Extracted the fuzz test's
`invariantViolations` into `dock/layoutInvariants.ts` (made area-aware: area
groups are referenced via `areas`, so they must not be flagged as orphans --
the one real difference from the fuzz original). `applyOp` asserts it on every
commit under `import.meta.env.DEV` (console.error, not throw -- a bad commit
shouldn't brick the UI). The fuzz suite imports the same function, so the app
and the fuzzer agree on "what valid means." Unit-tested in
`layoutInvariants.test.ts`. This catches the duplicate/orphan/double-reference
classes the instant a gesture or op produces them.

- **#2 `movePaneInPlace` primitive (detach-first).** Added the missing
pane-level analog of `detachInPlace` (the group-level choke point): detach the
pane from wherever it lives, THEN insert into the destination, so a pane can
never end up in two groups. `ensurePanelGroup`'s gather now moves stranger
panes back via this primitive (replacing the ad-hoc detach loop from the
drag-out-then-place fix). Validated by the fuzz suite + the re-gather op test.

- **Test factory (enabler).** Tests constructed FloatingWindow as ~100 raw
literals, coupling the model to test literals -- the real reason union refactors
were "expensive." Added `floatingWindow()` in testUtils as the one constructor;
routed makeLayout/floatingLayout through it; migrated every literal. After this,
#3a touched ZERO factory-routed literals (only ~4 stragglers + the assertions
that genuinely changed contract). Proves the model is now cheap to evolve.

- **#3a WindowHeight tagged union (DONE).** `FloatingWindow.height` is now
`{ mode: "auto" } | { mode: "pinned"; px: number }` (was `height?: number`).
Pin-trap + sentinel-undefined ambiguity unrepresentable; "revert to auto" is the
one named transition. The factory translates the terse `height?: number` test
opt, so call sites stayed terse; production reads branch on `.mode`. Verified:
403 vitest, 29 e2e, pin-trap re-confirmed end-to-end.

- **#3b float ownership as one `anchor` object (DONE -- lighter form).**
Replaced the `requestedX?`/`requestedY?` PAIR with a single `anchor?: {x; y}`.
PRESENCE is the ownership tag (anchored = re-resolves; absent = user-owned at
its absolute x/y). Collapsing the pair into one object makes "half-set
ownership" unrepresentable -- the exact hazard the study flagged (a resize that
set one coord but not the other). `markWindowUserOwned` is now a single
`delete win.anchor`. Stored absolute `x/y` are KEPT (hit-test/drag/render read
them unchanged), so this deliberately stops short of the full
`{kind:"anchored"}|{kind:"user"}` union with no stored x/y -- per the study,
that fuller union's extra win guards code the single-resolver already makes
single-writer, at 150+ lines of gesture-layer churn. The lighter form captures
the correctness win without touching the delicate grab-offset/grip code.
E2E seam: the Python `window()` helper in dock_helpers.py is the one place test
layouts build floating windows -- updated it for the WindowHeight union too.

- **Deferred / only-if-it-bites (from the studies):**
- Full `placement` tagged union (drop stored x/y; resolve at render): study
judged the incremental win guards code the single resolver already makes
single-writer, at 150+ lines of gesture-layer churn. Not worth it unless a
concrete drift bug demands it.
- Move panel-placement sync from React effects to one out-of-React store
subscription + a pure `reconcilePanel(layout, panel, record) -> layout`
(study 3). High value for killing the dep-array fragility, but medium risk
(control-panel width/theme/reset interplay). Extract the pure `reconcilePanel`
+ unit-test it first; do the subscription move only after that's stable.
Loading
Loading