Skip to content

D239 — The reading panel is resized by a splitter over the graph

Decision. The Atlas reading panel stays an overlay docked to the right of the graph, and a splitter on its left edge sets its width. The canvas never resizes: the camera's occludedRight follows the panel's rendered width instead. The width is a per-browser preference in localStorage (cartographer.inspector.width), clamped between 320px and what leaves 280px of graph beside the rail. A window resize re-clamps what is drawn and never the stored value. The splitter follows the WAI-ARIA window splitter pattern and is a reusable component (Splitter.tsx).

Why. The panel was too narrow to read long concepts. Keeping the overlay keeps the graph-first layout (D234, D235) and needs no change to the grid or to the canvas' resize handling. Deriving occludedRight from the rendered width also fixes a mismatch: the old constant ignored the 46% cap, so on a narrow desktop window the camera over-compensated. The cost: a wide panel hides more of a graph that is still drawn underneath it.

Alternatives rejected. - A grid column that resizes the canvas: every drag would resize the WebGL canvas and refit the camera, and the graph would lose its full-bleed area. - Keeping the width in the URL: it is not view state anyone shares. - A splitter library: Pointer Events with pointer capture cover it without a new runtime dependency. - Overwriting the stored width when a smaller window clamps it: the viewer's choice would shrink for good after one visit on a small screen.

Consequences. The panel's width lives in App.tsx state, measured against .shell__body and main; the shell re-measures when it mounts, the rail folds or the window resizes. Only a committed value (pointer up, a key, a reset) is written to storage. Splitter sizes any panel from either edge, so a later split (the planned artifacts list and detail) reuses it.