You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Complete the drag-foldable desktop left navigation, preserving its proven layout/state model, and finish the remaining interaction, accessibility, reflow, and integration work on the decided vanilla UI shell.
The left navigation participates in normal layout. It is never a desktop overlay or backdrop. Mobile keeps its segmented/bottom-navigation presentation and preserves desktop preferences for return to desktop.
Status
Architecture is decided — vanilla rendering per docs/ADR-0004-ui-shell.md (#577/#578 closed). Implementation routes through #587 (side-panel registry) and #586 (SurfaceLifecycle primitive + docked right-inspector slot, shared geometry with #488).
Phases 1–3 (PRs #571/#573/#574) were merged, then removed from main by the 2026-08-03 baseline reset. Restart from current main, salvaging proven work rather than re-deriving it: feat/left-nav-layout-core-487p1 (pure core/left-nav-layout.ts reducer, three-layout resize session), feat/nav-section-registry-487p2 (registry decisions — icon-as-factory, separate accessibleLabel, pane-scoped showSection, load-boundary key bridge — now being adapted by #587), feat/left-rail-focused-drawer-487p3 (rail/focused-drawer geometry, 180px drawer floor, per-section filters). The 2026-07-29 ship-log comment on this issue remains the historical record of the phase 1–3 implementation.
Proven foundations to salvage
Pull these from the branches above rather than re-deriving them:
Pure semantic layout core — src/core/left-nav-layout.ts owns semantic mode, focused-section coherence, thresholds, pointer/keyboard reducers, viewport clamping, and preferred/proposed/effective resize-session rules; it stays DOM-free.
Persistent section ownership — Databases, Dashboards, Library, and History each keep one logical host/state owner; presentation changes must not recreate search, expansion, loaded data, scroll, edit, or selection state.
Gesture memory and preference safety — resize sessions keep persisted preference, raw proposal, and effective viewport-clamped layout separate; temporary viewport constraints and pointer sampling must not corrupt the saved preferred width.
After a transition that hides or structurally reflows the focused navigation source completes, focus must settle on a visible, semantically sensible destination:
Transition
Destination
wide or focused drawer -> bare rail
matching rail launcher; separator fallback
rail/focused drawer -> wide
matching live wide-mode tab; separator fallback
focused drawer closed by Escape or launcher
matching rail launcher
desktop navigation -> mobile, including Tables
active mobile bottom-navigation button
mobile Tables -> Editor/Results
selected bottom-navigation button
mobile Query -> Dashboard
visible Editor route button
cancelled gesture or no semantic change
preserve current user focus
Transient intermediate frames (mid-drag, mid-fold) are unspecified — no requirement to capture intent before a destructive frame, freeze focus during drag repaint, or resolve stale-vs-superseded transition races. A transient focus on <body> during a drag is acceptable.
Teardown — remount, workspace switch, sign-out, or shell unmount — must dispose any pending focus/transition work; that is the only disposal rule.
Keep: no focus traps on the navigation surfaces, full keyboard reachability, visible focus, and Escape semantics consumed by the surface it closes.
The implementation may be a small imperative service or scheduler; it must not become a global application focus manager.
2. Separator discoverability
Closing a focused drawer relocates the 7px separator from the drawer edge to the rail edge. Make the new drag location discoverable — a brief visual emphasis or geometry transition, honoring prefers-reduced-motion — without a separate collapse button, without stealing keyboard focus, and without making animation necessary for correctness. Keep the separator keyboard reachable with visible focus.
3. Centre and right-panel reflow
Reflow every active centre surface — CodeMirror/editor geometry, result table and virtualized rows, editor/results split layout, Dashboard grids/flow layouts/charts/sticky bars, and the optional right inspector docked via #586 — through established observers or explicit layout hooks. The width budget must include left navigation, the optional right inspector, and a documented useful centre minimum; viewport clamping must not overwrite the preferred left width.
During a Library-query drag in rail mode: bounded hover on Dashboards opens the docked Dashboards drawer through the existing semantic controller seam; repeated hover notifications stay idempotent; drops work on Dashboard, Panels, and Filters targets; leaving/cancelling clears temporary hover state; semantic opening preempts an active resize session; the drawer never becomes an overlay.
5. Documentation and final verification
Document wide/rail/focused-drawer behavior and separator keyboard controls, and mobile preference preservation; reconcile roadmap/changelog references including #586/#587; verify simultaneous left/right docking with #488 in Chromium and WebKit.
Tests
Unit coverage
semantic origin/destination transition matrix (final settled state only);
disposal cancels pending focus/transition work on teardown;
a completed structural transition never ends on <body> when a semantic destination exists;
centre reflow with and without the right inspector.
Implementation notes: multi-frame drag/focus racing and stale-vs-current transition ordering are useful guidance if the pre-reset branches' approach is worth reusing, but they are not acceptance gates.
Acceptance criteria
Wide, rail, and focused-drawer presentations follow the documented geometry and never use a desktop overlay.
All four sections preserve their domain/UI state across presentation changes.
Mode and width preferences decode safely, survive viewport clamps, and remain outside workspace/query/Dashboard documents.
Pointer and keyboard separator behavior is deterministic and does not corrupt stored preference.
Rail clicks, Escape, drag hover, and programmatic reveals cannot be overwritten by stale resize work.
Mobile never renders the desktop rail/drawer and preserves desktop preference for return to desktop.
Structural transitions settle focus on a visible semantic destination once complete.
The relocated separator is discoverable without mandatory motion or focus stealing.
Left/right docked panels and every centre surface reflow while retaining the documented centre minimum.
Goal
Complete the drag-foldable desktop left navigation, preserving its proven layout/state model, and finish the remaining interaction, accessibility, reflow, and integration work on the decided vanilla UI shell.
Desktop presentations remain:
The left navigation participates in normal layout. It is never a desktop overlay or backdrop. Mobile keeps its segmented/bottom-navigation presentation and preserves desktop preferences for return to desktop.
Status
Architecture is decided — vanilla rendering per
docs/ADR-0004-ui-shell.md(#577/#578 closed). Implementation routes through #587 (side-panel registry) and #586 (SurfaceLifecycleprimitive + docked right-inspector slot, shared geometry with #488).Phases 1–3 (PRs #571/#573/#574) were merged, then removed from
mainby the 2026-08-03 baseline reset. Restart from currentmain, salvaging proven work rather than re-deriving it:feat/left-nav-layout-core-487p1(purecore/left-nav-layout.tsreducer, three-layout resize session),feat/nav-section-registry-487p2(registry decisions — icon-as-factory, separateaccessibleLabel, pane-scopedshowSection, load-boundary key bridge — now being adapted by #587),feat/left-rail-focused-drawer-487p3(rail/focused-drawer geometry, 180px drawer floor, per-section filters). The 2026-07-29 ship-log comment on this issue remains the historical record of the phase 1–3 implementation.Proven foundations to salvage
Pull these from the branches above rather than re-deriving them:
src/core/left-nav-layout.tsowns semantic mode, focused-section coherence, thresholds, pointer/keyboard reducers, viewport clamping, and preferred/proposed/effective resize-session rules; it stays DOM-free.Remaining product work
1. Focus settlement after structural transitions
After a transition that hides or structurally reflows the focused navigation source completes, focus must settle on a visible, semantically sensible destination:
Transient intermediate frames (mid-drag, mid-fold) are unspecified — no requirement to capture intent before a destructive frame, freeze focus during drag repaint, or resolve stale-vs-superseded transition races. A transient focus on
<body>during a drag is acceptable.Teardown — remount, workspace switch, sign-out, or shell unmount — must dispose any pending focus/transition work; that is the only disposal rule.
Keep: no focus traps on the navigation surfaces, full keyboard reachability, visible focus, and Escape semantics consumed by the surface it closes.
The implementation may be a small imperative service or scheduler; it must not become a global application focus manager.
2. Separator discoverability
Closing a focused drawer relocates the 7px separator from the drawer edge to the rail edge. Make the new drag location discoverable — a brief visual emphasis or geometry transition, honoring
prefers-reduced-motion— without a separate collapse button, without stealing keyboard focus, and without making animation necessary for correctness. Keep the separator keyboard reachable with visible focus.3. Centre and right-panel reflow
Reflow every active centre surface — CodeMirror/editor geometry, result table and virtualized rows, editor/results split layout, Dashboard grids/flow layouts/charts/sticky bars, and the optional right inspector docked via #586 — through established observers or explicit layout hooks. The width budget must include left navigation, the optional right inspector, and a documented useful centre minimum; viewport clamping must not overwrite the preferred left width.
4. #428 drag-and-drop integration
During a Library-query drag in rail mode: bounded hover on Dashboards opens the docked Dashboards drawer through the existing semantic controller seam; repeated hover notifications stay idempotent; drops work on Dashboard, Panels, and Filters targets; leaving/cancelling clears temporary hover state; semantic opening preempts an active resize session; the drawer never becomes an overlay.
5. Documentation and final verification
Document wide/rail/focused-drawer behavior and separator keyboard controls, and mobile preference preservation; reconcile roadmap/changelog references including #586/#587; verify simultaneous left/right docking with #488 in Chromium and WebKit.
Tests
Unit coverage
Real-browser coverage
Chromium and WebKit must cover:
<body>when a semantic destination exists;Implementation notes: multi-frame drag/focus racing and stale-vs-current transition ordering are useful guidance if the pre-reset branches' approach is worth reusing, but they are not acceptance gates.
Acceptance criteria
Non-goals
setTimeoutfocus or resize guesses.Related
SurfaceLifecycleprimitive and docked right-inspector slot (shared shell geometry).