Wave-5 refinement round 5 (owner): glyph-shaped SVG marks, vertically centered
- Option rows: items-start → items-center — the icon span's top-misalign came from the row alignment; now marks center across the row. - The literal ✓/✗ look (owner preference over the round-3 lucide set) re-rendered as hand-rolled SVG with thick rounded strokes (strokeWidth 3, round caps/joins) — the glyph shape, as a true vector, sized like the row text. Test pins updated to data-mark=check|x.
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { CheckIcon, XIcon } from "lucide-react";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { MessageResponse } from "@/components/ai-elements/message";
|
import { MessageResponse } from "@/components/ai-elements/message";
|
||||||
import type { QuestionAnswerData } from "@/src/core";
|
import type { QuestionAnswerData } from "@/src/core";
|
||||||
@@ -51,7 +50,7 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
|||||||
<div
|
<div
|
||||||
key={opt.index}
|
key={opt.index}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-start gap-2 rounded-lg border px-3 py-1.5",
|
"flex items-center gap-2 rounded-lg border px-3 py-1.5",
|
||||||
sel && key && "border-green-500/60 bg-green-500/10",
|
sel && key && "border-green-500/60 bg-green-500/10",
|
||||||
sel && !key && isQuiz && "border-red-500/60 bg-red-500/10",
|
sel && !key && isQuiz && "border-red-500/60 bg-red-500/10",
|
||||||
sel && !isQuiz && "border-primary bg-accent",
|
sel && !isQuiz && "border-primary bg-accent",
|
||||||
@@ -59,19 +58,33 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isQuiz && (
|
{isQuiz && (
|
||||||
// SVG icons, not glyphs — exactly one text-size box (size-4),
|
// Hand-rolled SVG in the ✓/✗ GLYPH look (thick rounded strokes —
|
||||||
// vertically centered in the flex row (owner).
|
// owner prefers that shape but as vectors, round 5). Sized like
|
||||||
|
// the row text, centered (row is items-center).
|
||||||
<span
|
<span
|
||||||
aria-hidden
|
aria-hidden
|
||||||
|
data-mark={sel && key ? "check" : sel && !key ? "x" : !sel && key ? "check" : undefined}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex size-4 shrink-0 items-center justify-center",
|
"flex shrink-0 items-center",
|
||||||
sel && key && "text-green-500",
|
sel && key && "text-green-500",
|
||||||
sel && !key && "text-red-500",
|
sel && !key && "text-red-500",
|
||||||
!sel && key && "text-green-500",
|
!sel && key && "text-green-500",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{key && <CheckIcon className="size-4" strokeWidth={2.5} />}
|
{(sel && key) || (!sel && key) ? (
|
||||||
{sel && !key && <XIcon className="size-4" strokeWidth={2.5} />}
|
<svg viewBox="0 0 16 16" className="size-4" fill="none" stroke="currentColor"
|
||||||
|
strokeWidth={3} strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M3 8.5 L6.5 12 L13 4.5" />
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
sel &&
|
||||||
|
!key && (
|
||||||
|
<svg viewBox="0 0 16 16" className="size-4" fill="none" stroke="currentColor"
|
||||||
|
strokeWidth={3} strokeLinecap="round">
|
||||||
|
<path d="M4 4 L12 12 M12 4 L4 12" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span className={cn(!sel && "text-muted-foreground")}>
|
<span className={cn(!sel && "text-muted-foreground")}>
|
||||||
@@ -86,7 +99,7 @@ export function AnsweredCard({ answer }: { answer: QuestionAnswerData }) {
|
|||||||
{answer.other && (
|
{answer.other && (
|
||||||
<div
|
<div
|
||||||
data-testid="answered-other"
|
data-testid="answered-other"
|
||||||
className="flex items-start gap-2 rounded-lg border border-primary bg-accent px-3 py-1.5"
|
className="flex items-center gap-2 rounded-lg border border-primary bg-accent px-3 py-1.5"
|
||||||
>
|
>
|
||||||
<span>“{answer.other}”</span>
|
<span>“{answer.other}”</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -168,8 +168,8 @@ describe("render smoke tests", () => {
|
|||||||
const html = renderToStaticMarkup(<AnsweredCard answer={answer} />);
|
const html = renderToStaticMarkup(<AnsweredCard answer={answer} />);
|
||||||
assert.match(html, /incorrect/);
|
assert.match(html, /incorrect/);
|
||||||
assert.match(html, /innermost/, "explanation renders post-answer");
|
assert.match(html, /innermost/, "explanation renders post-answer");
|
||||||
// Vector marks (lucide SVG) — not glyphs — sized like the row text (owner).
|
// Glyph-shaped SVG marks (owner preference) — pinned via data-mark.
|
||||||
assert.ok(html.includes("lucide-check") && html.includes("lucide-x"));
|
assert.ok(html.includes('data-mark="check"') && html.includes('data-mark="x"'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("AnsweredCard renders the learner's own Other answer AS an option row", () => {
|
it("AnsweredCard renders the learner's own Other answer AS an option row", () => {
|
||||||
@@ -214,7 +214,7 @@ describe("render smoke tests", () => {
|
|||||||
};
|
};
|
||||||
const answer = buildAnswer(qd, { values: ["Somewhat"] });
|
const answer = buildAnswer(qd, { values: ["Somewhat"] });
|
||||||
const html = renderToStaticMarkup(<AnsweredCard answer={answer} />);
|
const html = renderToStaticMarkup(<AnsweredCard answer={answer} />);
|
||||||
assert.ok(!html.includes("incorrect") && !html.includes("lucide-x"), "ask answers never get quiz grading UI");
|
assert.ok(!html.includes("incorrect") && !html.includes('data-mark="x"'), "ask answers never get quiz grading UI");
|
||||||
assert.match(html, /Somewhat/);
|
assert.match(html, /Somewhat/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user