UI iteration 1: app shell + full LaTeX pipeline
Layout:
- Home = knowledge-graph placeholder (main view) with new-session input
docked below; session list moved out of home into a hamburger drawer
- SessionDrawer: slide-over session navigation (backdrop/ESC close, active
highlight, fetches /api/chats on open) on both home and chat headers
- Chat header loses the back button — the drawer is the navigation
Math (inline $ was silently not rendering):
- @streamdown/math defaults singleDollarTextMath:false — now
createMathPlugin({ singleDollarTextMath: true }) in message + reasoning
- katex.min.css imported in layout (streamdown does not inject plugin
styles; display math only looked right via browser MathML fallback)
- QuizCard/AnsweredCard route question/options/explanation through
MessageResponse; user chat bubbles render markdown+math too
- Currency hazard: micromark-extension-math@3.1 lacks pandoc's
closing-digit rule, so bare '$5 and $10' parses as math — defense is at
the source: system prompt now instructs escaped \$5 / 'USD' for money
Hydration fix (React #418):
- QuizCard shuffled options with Math.random() — server/client orders
diverged. shuffleOptions now takes an injectable RNG; QuizCard passes
seededRandom(toolCallId) (mulberry32/FNV-1a in question-core). Same
question → same stable order across reloads; still varies per question.
Tests: 53 pass (5 new math-rendering pins incl. fenced-vs-one-line $$
behavior and the escaped-currency contract). tsc + next build clean.
Verified live in browser: inline/display math in text + cards, drawer
open/navigate/active-highlight/ESC, no console errors, no font 404s.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { MessageResponse } from "@/components/ai-elements/message";
|
||||
import type { QuestionAnswerData } from "@/src/core/question-core";
|
||||
|
||||
/**
|
||||
@@ -36,7 +37,9 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
||||
<span className="rounded bg-red-500/15 px-1.5 py-0.5 text-red-500">incorrect</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="mb-3 font-medium">{answer.questionText}</div>
|
||||
<div className="mb-3 font-medium">
|
||||
<MessageResponse>{answer.questionText}</MessageResponse>
|
||||
</div>
|
||||
|
||||
{answer.options && answer.options.length > 0 && (
|
||||
<div className="flex flex-col gap-1.5 text-sm">
|
||||
@@ -61,7 +64,9 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
||||
{!sel && key && "✓"}
|
||||
</span>
|
||||
)}
|
||||
<span className={cn(!sel && "text-muted-foreground")}>{opt.label}</span>
|
||||
<span className={cn(!sel && "text-muted-foreground")}>
|
||||
<MessageResponse>{opt.label}</MessageResponse>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -75,7 +80,7 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
||||
{isQuiz && answer.explanation && (
|
||||
<div className="mt-3 rounded-lg bg-muted px-3 py-2 text-sm text-muted-foreground">
|
||||
<span className="font-medium text-foreground">Why: </span>
|
||||
{answer.explanation}
|
||||
<MessageResponse className="inline">{answer.explanation}</MessageResponse>
|
||||
</div>
|
||||
)}
|
||||
{answer.note && <div className="mt-2 text-xs text-muted-foreground">Note: {answer.note}</div>}
|
||||
|
||||
Reference in New Issue
Block a user