"use client"; import { cn } from "@/lib/utils"; import { MessageResponse } from "@/components/ai-elements/message"; import type { QuestionAnswerData } from "@/src/core"; /** * Static rendering of an answered question (tool part in `output-available`). * * Quiz answers are GRADED: ✓/✗ marks, the correct answers, and the * explanation. Ask answers are NOT graded — a plain record of what was said. * (The v1 bug this pins: ask answers must never get quiz grading UI.) */ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) { if (answer.dismissed) { return (
{answer.questionText} — skipped
); } const isQuiz = answer.kind === "quiz"; const selectedIdx = new Set(answer.answers.map((a) => a.index)); const correctIdx = new Set(answer.correctIndices ?? []); return (
{isQuiz ? "Quiz" : "Question"} {isQuiz && (answer.dontKnow ? ( didn't know ) : answer.correct ? ( correct ) : ( incorrect ))}
{answer.questionText}
{((answer.options?.length ?? 0) > 0 || answer.other) && (
{answer.options?.map((opt) => { const sel = selectedIdx.has(opt.index); const key = isQuiz && correctIdx.has(opt.index); return (
{isQuiz && ( // Hand-rolled SVG in the ✓/✗ GLYPH look (thick rounded strokes — // owner prefers that shape but as vectors, round 5). Sized like // the row text, centered (row is items-center). {(sel && key) || (!sel && key) ? ( ) : ( sel && !key && ( ) )} )} {opt.label}
); })} {/* The learner's own typed option is an OPTION — same container, same selected styling as its siblings, not a loose quote floating outside the list. Quotes keep the learner's words. */} {answer.other && (
“{answer.other}”
)}
)} {answer.text &&
“{answer.text}”
} {answer.dontKnow && isQuiz &&
Answered “I don't know”.
} {answer.note && (
Your thinking {answer.note}
)} {/* px-3→removed: card p-4 + box px-3 double-inset sat the "Why" label deeper than the option box edges (owner, round 3). Sides flush with everything else; py-2 stays for vertical air. */} {isQuiz && answer.explanation && (
Why: {/* The markdown wrapper must go truly inline — a block

after the "Why:" label created the oversized leading gap (owner's fix list). */} {answer.explanation}

)}
); }