ui: intent-gated fold, measured height caps, the Problem eyebrow, fold fade

Owner round (2026-10-05), Slice D — the dock mechanics:

- INTENT-GATED FOLD: a ResizeObserver on the scroller's content stamps
  the existing 400ms mute whenever the transcript GROWS — growth frames
  (a live turn streaming under stick-to-bottom's chase) can never fold
  the dock; and a fold now needs the distance AND stick-to-bottom's
  isAtBottom agreeing the learner left. Fixes the generation churn
  (dock disappearing and reappearing while the agent works). Shrinks
  stamp nothing (the fold's own morph must not self-mute re-expand).
- MEASURED HEIGHT CAPS: the question (55dvh) and problem (40vh) areas
  now cap at the available column (scroller clientHeight − 2rem,
  re-measured on resize) via --dock-max-h — questions stretch to the
  top bar with sensible padding and scroll internally only when
  genuinely huge.
- The practice dock's statement area carries the 'Problem' eyebrow —
  the quiz cards' label row, mirrored (dock and transcript card read
  identically).
- The fold's CONTENT fade: a 160ms WAAPI fade/rise on the bar↔form
  toggle — no remount, so the question form's state survives; the
  shell height morph was already animated.
This commit is contained in:
amosblomqvist
2026-10-05 02:31:55 +03:00
parent 5d253a933c
commit a5a554582e
4 changed files with 75 additions and 8 deletions
+6 -2
View File
@@ -92,8 +92,12 @@ export function PracticeDock({ problemCallId, input, expanded, onExpand, onSubmi
/* ── the expanded form ── */
return (
<div data-testid="practice-dock" data-problem={problemCallId}>
{/* The agent's half: the statement, markdown + LaTeX rendered. */}
<div className="max-h-[40vh] overflow-y-auto px-4 pt-3 pb-2">
{/* The agent's half: the 'Problem' eyebrow (mirroring the quiz
cards' label row — owner round, 2026-10-05) + the statement,
markdown + LaTeX rendered, capped by the measured column
(--dock-max-h; the old fixed 40vh cut long problems short). */}
<div className="max-h-[var(--dock-max-h,40vh)] overflow-y-auto px-4 pt-3 pb-2">
<div className="mb-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">Problem</div>
<div className="lh-prose text-[15px]">
<MessageResponse>{input.statement}</MessageResponse>
</div>