Altinity / Altinity/altinity-sql-browser
Add a drag-foldable desktop left navigation with rail and focused drawers
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- TypeScript
- Estrellas
- 8
- Forks
- 2
- Merge medio
- 1 h 34 min
- PR fusionados (30 d)
- 6
Descripción
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:
wide
[two-pane sidebar] [main Query/Dashboard surface] [optional right inspector]
rail
[48px rail] [main Query/Dashboard surface] [optional right inspector]
focused drawer
[48px rail] [one docked navigation section] [main surface] [optional right inspector]
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.tsowns 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.
- One presentation owner — #587's side-panel registry (section ownership) and #586's docked layout (shared geometry with the right inspector) together own navigation geometry, visibility, pane exposure, separator state, and ARIA presentation; no second, competing owner for the same subtree.
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:
| 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.
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
- semantic origin/destination transition matrix (final settled state only);
- disposal cancels pending focus/transition work on teardown;
- preferred width survives effective viewport clamps;
- separator keyboard and pointer behavior remain equivalent.
Real-browser coverage
Chromium and WebKit must cover:
- wide search/tree focus -> fold -> matching rail launcher;
- focused drawer -> fold -> matching launcher;
- drawer/rail -> wide -> matching live tab;
- desktop -> mobile Editor, Results, and Tables;
- mobile Tables -> Editor/Results;
- mobile Query -> Dashboard;
- Escape/launcher close;
- Home/End separator behavior;
- 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.
- #428 drag-hover/drop integration works in rail mode without overlays or state flapping.
- Chromium and WebKit prove CSS visibility, final-state focus settlement, mobile/surface transitions, and combined left/right layout.
Non-goals
- A desktop overlay drawer or backdrop.
- Duplicate navigation hosts or stores.
- DOM focus knowledge in the pure layout reducer.
- Arbitrary
setTimeoutfocus or resize guesses. - Animation as a correctness dependency.
- Automatically reopening the last focused drawer after reload.
- Requirements on transient mid-gesture focus behavior.
Related
- #586 —
SurfaceLifecycleprimitive and docked right-inspector slot (shared shell geometry). - #587 — side-panel registry this issue's section host routes through.
- #488 — right inspector and shared left/right centre-width behavior.
- #428 — Dashboard drag-and-drop integration.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza en src/core/left-nav-layout.ts y current main, y después inspecciona las ramas probadas feat/left-nav-layout-core-487p1, feat/nav-section-registry-487p2 y feat/left-rail-focused-drawer-487p3. Sigue la integración a través de #586 y #587, y después ejecuta la cobertura de Chromium y WebKit descrita en el issue; terminado significa que todas las transiciones, el reflow, las comprobaciones de arrastrar y soltar, accesibilidad, documentación y aceptación enumeradas pasan sin overlays de escritorio.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- accessibility, documentation, frontend, testing-qa
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 35/100