Skip to content

Add a drag-foldable desktop left navigation with rail and focused drawers #487

Description

@BorisTyshkevich

Goal

Complete the drag-foldable desktop left navigation while preserving its shipped layout/state model and finishing the remaining interaction, accessibility, reflow, and integration work on the application’s selected UI-shell architecture.

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 and architecture dependency

If #577 selects Preact, the remaining implementation is Phase 2 of the migration umbrella #578. If Preact is rejected, complete the same product behavior with the smaller targeted vanilla design recorded by the #577 ADR.

This issue no longer prescribes a left-nav-focus.ts, shell-focus-transitions.ts, hook, component, or global focus manager. The behavior is fixed; the implementation boundary is selected by #577.

Shipped foundations to retain

The following design decisions are proven and should survive any rendering-layer migration:

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 remains DOM-free.

Persistent section ownership

Databases, Dashboards, Library, and History each retain 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

The selected UI-shell architecture must provide one owner for navigation geometry, visibility, pane exposure, separator state, and ARIA presentation. Do not create competing vanilla and Preact owners for the same subtree.

Remaining product work

1. Structural focus continuity

Any transition that hides or structurally reflows the focused navigation source must settle focus on a visible semantic destination.

Required behavior:

  • capture semantic intent before the first destructive transition frame;
  • preserve that intent through intermediate pointer-drag frames;
  • do not restore focus during live drag repaint;
  • settle after the destination is rendered and browser layout is stable;
  • cancel stale or superseded transition work;
  • do not steal focus after the user has moved to another visible control;
  • do not leave focus on <body> merely because application chrome changed presentation;
  • dispose pending transition work during remount, workspace switch, sign-out, or shell teardown.

Destination policy when focus originated in navigation:

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

The implementation may be a component lifecycle, hook, tiny scheduler plus feature policy, or small imperative service. It must not become a global application focus manager without evidence from #577.

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 without adding a separate collapse button.

Requirements:

  • use a brief visual emphasis or geometry transition selected through implementation review;
  • honor prefers-reduced-motion;
  • do not steal keyboard focus;
  • do not make animation necessary for correctness;
  • keep the separator keyboard reachable with visible focus.

3. Centre and right-panel reflow

Reflow every active centre surface 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 remain idempotent;
  • drops work on Dashboard, Panels, and Filters targets;
  • leaving or cancelling clears temporary hover state;
  • semantic opening preempts an active resize session;
  • the drawer never becomes an overlay.

5. Documentation and final verification

Tests

Architecture-independent unit coverage

  • semantic origin/destination transition matrix;
  • pointer capture survives multiple intermediate frames;
  • cancellation and superseding behavior;
  • user-moved-focus abort behavior;
  • disposal cancels pending work;
  • 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 -> multi-step fold -> matching rail launcher;
  • focused drawer -> multi-step fold -> matching launcher;
  • non-monotone drag paths without intermediate focus movement;
  • 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;
  • no structural transition ends on <body> when a semantic destination exists;
  • no stale transition steals focus after a newer user action;
  • centre reflow with and without the right inspector.

Acceptance criteria

  1. Wide, rail, and focused-drawer presentations follow the documented geometry and never use a desktop overlay.
  2. All four sections preserve their domain/UI state across presentation changes.
  3. Mode and width preferences decode safely, survive viewport clamps, and remain outside workspace/query/Dashboard documents.
  4. Pointer and keyboard separator behavior is deterministic and does not corrupt stored preference.
  5. Rail clicks, Escape, drag hover, and programmatic reveals cannot be overwritten by stale resize work.
  6. Mobile never renders the desktop rail/drawer and preserves desktop preference for return to desktop.
  7. Structural transitions settle focus on a visible semantic destination without stealing newer user focus.
  8. The relocated separator is discoverable without mandatory motion or focus stealing.
  9. Left/right docked panels and every centre surface reflow while retaining the documented centre minimum.
  10. Add Library drag assignment to Dashboard panels and variables #428 drag-hover/drop integration works in rail mode without overlays or state flapping.
  11. Chromium and WebKit prove CSS visibility, focus settlement, multi-frame gestures, mobile/surface transitions, and combined left/right layout.
  12. If implemented through Migrate the application UI to Preact in measured simplification phases #578, the migrated navigation deletes the vanilla presentation/lifecycle paths it replaces and reduces production UI complexity.

Non-goals

  • A desktop overlay drawer or backdrop.
  • Duplicate navigation hosts or stores.
  • DOM focus knowledge in the pure layout reducer.
  • Arbitrary setTimeout focus or resize guesses.
  • Animation as a correctness dependency.
  • Automatically reopening the last focused drawer after reload.
  • Selecting Preact or defining the whole-application migration inside this feature issue.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions