Plan placement (owner): the plan as marginalia — dock band's right flank + top-bar chip

Retires the fixed bottom-left plan window (which sat ON the sidebar and
bled into the session). Two placements replace it, per the owner's
lock-in:

- The plan chip in the top bar beside the phase chip — session-level
  structure beside session state; opens the full-DAG popup; present at
  every width; the access point.
- The plan marginalia: the BARE diagram (no card, no border, no shadow)
  in the dock band's right flank — marginalia on the lesson's page, not a
  floating widget. The band's reserved height (tall while a quiz is
  open) is its canvas; meet-fitted (PlanDiagram's new fill mode) so it
  fits both the flank's width and the band's height; live statuses +
  the yellow current-node glow; click opens the popup. Mounted only
  while a question owns the band — composer mode keeps the reading
  view pristine. Folding the dock fades + blurs it out of existence
  (300ms), returning to the bottom fades it back in. Rendered only when
  the flank holds a real diagram (>= 240px); narrower windows keep the
  chip alone.

Files: chat.tsx (chip, DockOverlay marginalia wrapper + flank measure,
PlanWindow removed), plan-window.tsx (PlanWindow → PlanMarginalia),
plan-block.tsx (PlanDiagram fill prop: h-full w-full meet-fit),
tests/plan-window.test.tsx (rewritten for the marginalia).
This commit is contained in:
amosblomqvist
2026-09-14 11:23:28 +03:00
parent 873c153525
commit 93033fac77
4 changed files with 146 additions and 149 deletions
+7 -1
View File
@@ -358,6 +358,7 @@ export function PlanDiagram({
textCapScale,
naturalSize,
monochrome,
fill,
}: {
nodes: readonly LayoutNode[];
edges: ReadonlyArray<{ from: string; to: string }>;
@@ -379,6 +380,11 @@ export function PlanDiagram({
/** The in-chat block's mode: every node white (fill-none, white stroke
* and text, no glow) — statuses never show in the transcript (owner). */
monochrome?: boolean;
/** Meet-fits the diagram inside a fixed box (h-full w-full — the svg's
* default preserveAspectRatio centers + contains the viewBox): the
* dock band's marginalia mode, where the diagram must fit BOTH the
* flank's width and the band's height rather than run width-first. */
fill?: boolean;
}) {
const layout = useMemo(() => blockLayout(nodes, edges), [nodes, edges]);
// Pad only the full-extent render — the plan window's override viewBox is
@@ -391,7 +397,7 @@ export function PlanDiagram({
return (
<svg
viewBox={viewBoxOverride ?? `${-pad} ${-pad} ${vbW} ${vbH}`}
className={`block h-auto${naturalSize ? "" : " w-full"}${textCapScale ? " mx-auto" : ""}`}
className={`block ${fill ? "h-full w-full" : `h-auto${naturalSize ? "" : " w-full"}`}${textCapScale ? " mx-auto" : ""}`}
style={
textCapScale
? { maxWidth: `${Math.round(vbW * textCapScale * 100) / 100}px` }