ControlRail — a slim, always-visible vertical activity rail docked to the
left edge of the viewer.
Luxar's UI is otherwise entirely keyboard-triggered (H, N, R, L, P, O, …),
which means a first-time visitor sees a bare canvas with no hint that any
controls exist. The rail fixes that: one discoverable, recognizable icon per
panel, each wired to the exact same command the keyboard shortcut fires
(via InputHandler.getUiActions), with a tooltip showing the shortcut.
Design notes:
Matches the viewer design tokens (--luxar-*), so it themes for all four
themes automatically.
Idle-dims after a few seconds of no pointer movement so it recedes into the
immersive canvas, and wakes on pointer movement / hover.
Reflects live open/closed state per panel (active highlight).
Shows a one-time first-run hint (localStorage-gated) pointing at itself;
it auto-fades after a few seconds and any click/routed shortcut dismisses it.
The flyout + panel-popover lifecycle lives in RailOverlay
(control-rail/rail-overlay.ts); this class owns the buttons, idle/collapse/fullscreen
behaviour, and the active-state refresh that reads the overlay's open item.
ControlRail — a slim, always-visible vertical activity rail docked to the left edge of the viewer.
Luxar's UI is otherwise entirely keyboard-triggered (H, N, R, L, P, O, …), which means a first-time visitor sees a bare canvas with no hint that any controls exist. The rail fixes that: one discoverable, recognizable icon per panel, each wired to the exact same command the keyboard shortcut fires (via InputHandler.getUiActions), with a tooltip showing the shortcut.
Design notes:
--luxar-*), so it themes for all four themes automatically.The flyout + panel-popover lifecycle lives in RailOverlay (control-rail/rail-overlay.ts); this class owns the buttons, idle/collapse/fullscreen behaviour, and the active-state refresh that reads the overlay's open item.