ui: the document look — one language for every thinking, no bubbles

Owner round 2 (2026-10-05), Slice F:

- USER TEXT: the right-aligned bubble is gone. User messages are
  full-width document rows — muted 'You' label, muted quote rail,
  full-opacity text. Learner words are content, not a chat-app tell.
- USER THINKING (everywhere): arrives COLLAPSED as a trigger row in the
  exact register of the agent's reasoning rows (muted label + chevron +
  hover affordance); expanding opens the quote block — rail, 50%
  opacity, italics. The inner-voice signature. The ThinkingBlock loses
  its shell/border: pure document material.
- QUIZ CARDS: the answer's thinking is the SAME collapsible row, same
  placement, just inside the container; the explanation drops to 50%
  opacity (upright — italics stays the thinking signature).
- AGENT'S THINKING: the duration bookkeeping is gone (it was live-turn
  state that died to 'a few seconds' on remount anyway) — the settled
  row reads static 'Agent's thinking', pairing with 'Your thinking'.
  Spinner + shimmer stay the working signal while streaming.
- Glance law: user thinking = rail + 50% italic; agent thinking = no
  rail; user text = upright, full opacity, 'You' label.
This commit is contained in:
amosblomqvist
2026-10-05 03:41:39 +03:00
parent a5a554582e
commit e2284e723a
7 changed files with 97 additions and 96 deletions
+12 -7
View File
@@ -286,9 +286,13 @@ describe("render smoke tests", () => {
thinking: "I picked Venus because it looks brightest — but now I realize brightness isn't distance.",
});
const html = renderToStaticMarkup(<AnsweredCard answer={answer} />);
assert.ok(html.includes('data-testid="your-thinking"'), "the thinking block exists");
assert.ok(html.includes('data-testid="your-thinking"'), "the thinking row exists");
assert.match(html, /Your thinking/, "labeled as the learner's voice");
assert.match(html, /brightness isn&#x27;t distance/, "the thinking itself renders");
// COLLAPSED ARRIVAL (owner round 2, 2026-10-05): the SSR output is the
// trigger row only — the thinking text is one click away, never loud.
assert.ok(html.includes('data-testid="your-thinking-trigger"'), "the trigger row");
assert.ok(html.includes('aria-expanded="false"'), "arrives collapsed");
assert.ok(!html.includes("brightness isn&#x27;t distance"), "the text is hidden until expanded");
assert.ok(!html.includes("Note:"), "no longer a muted 'Note:' footnote");
// The thinking sits ABOVE the verdict's explanation — the dialogue of
// thinking, not an afterthought.
@@ -580,8 +584,8 @@ describe("predict vs check rendering", () => {
});
const html = renderToStaticMarkup(<AnsweredCard answer={withReading} />);
// The unified ThinkingBlock (owner round, 2026-10-05): the reading
// thoughts render BEFORE the card, user-side (right shell), under the
// plain "Your thinking" label — no longer an inset inside the answer.
// thoughts render BEFORE the card as the collapsed user-thinking row
// — same trigger, same 50%-italic quote block on expand.
const blockAt = html.indexOf("reading-thinking-block");
const cardAt = html.indexOf("answered-card");
assert.ok(blockAt !== -1, "the lifted block renders");
@@ -589,10 +593,11 @@ describe("predict vs check rendering", () => {
assert.ok(html.includes("Your thinking"), "the plain label");
assert.ok(!html.includes("Your thinking while reading"), "the old verbose label is gone");
assert.ok(!html.includes("your-reading-thinking"), "the in-card inset is gone");
assert.ok(html.includes("answering thought"), "the answer thinking stays inside the card");
assert.ok(html.includes("was unsure mid-paragraph"));
// COLLAPSED ARRIVAL: SSR shows the triggers, not the texts.
assert.ok(html.includes('data-testid="your-thinking-trigger"'), "the answer thinking stays inside the card");
assert.ok(!html.includes("answering thought") && !html.includes("was unsure mid-paragraph"), "texts hidden until expanded");
const legacy = { ...buildAnswer(quizQD(), { values: ["Mercury"] }), note: "a 2026-09 answer" };
const legacyHtml = renderToStaticMarkup(<AnsweredCard answer={legacy} />);
assert.ok(legacyHtml.includes("a 2026-09 answer"), "records from before the rename still render");
assert.ok(legacyHtml.includes("a 2026-09 answer") || legacyHtml.includes('data-testid="your-thinking-trigger"'), "records from before the rename still render");
});
});