fix: clarify defense qna modal hierarchy

This commit is contained in:
lda
2026-07-09 04:51:11 +07:00 Verified
parent fe1f3f90e1
commit 645e4ffbf1
3 changed files with 123 additions and 51 deletions
@@ -93,6 +93,26 @@ describe("DiscussionPanel", () => {
expect(note).toHaveClass("discussion-panel__presenter-note");
});
it("separates Q&A answer, provenance, and presenter note regions", () => {
render(<DiscussionPanel branchId="where-is-ai-agent" onClose={onClose} />);
const dialog = screen.getByRole("dialog");
expect(dialog).toHaveAttribute("data-discussion-layout", "qna");
expect(screen.getByLabelText("short defense answer")).toHaveTextContent(/workflow substrate/i);
expect(screen.getByLabelText("answer expansion")).toHaveTextContent(/planning algorithm/i);
expect(screen.getByLabelText("answer provenance")).toHaveTextContent(/Abstract/i);
expect(screen.getByLabelText("presenter note")).toHaveTextContent(/Answer directly first/i);
});
it("uses context layout for non-Q&A discussion branches", () => {
render(<DiscussionPanel branchId="hosted-automation" onClose={onClose} />);
const dialog = screen.getByRole("dialog");
expect(dialog).toHaveAttribute("data-discussion-layout", "context");
expect(screen.queryByLabelText("short defense answer")).not.toBeInTheDocument();
expect(screen.getByLabelText("answer provenance")).toHaveTextContent(/Workflow Automation Platforms/i);
});
it("shows mcp-agent-scale links to Anthropic and Cloudflare", () => {
render(<DiscussionPanel branchId="mcp-agent-scale" onClose={onClose} />);
const anthropic = screen.getByText("Anthropic MCP");
@@ -22,6 +22,8 @@ export const DiscussionPanel = ({ branchId, onClose }: DiscussionPanelProps) =>
if (!branch) return null;
const hasQuestion = branch.question !== undefined;
const parentScene = findScene(branch.parentSceneId);
const trapKeyboardWithinDialog = (event: KeyboardEvent<HTMLDivElement>) => {
@@ -51,6 +53,7 @@ export const DiscussionPanel = ({ branchId, onClose }: DiscussionPanelProps) =>
ref={dialogRef}
className="discussion-panel"
data-presentation-surface="editorial"
data-discussion-layout={hasQuestion ? "qna" : "context"}
role="dialog"
aria-modal="true"
aria-label={branch.title}
@@ -60,36 +63,47 @@ export const DiscussionPanel = ({ branchId, onClose }: DiscussionPanelProps) =>
<h2>{branch.title}</h2>
<span className="discussion-panel__badge">{branch.claimClass}</span>
</header>
<p className="discussion-panel__evidence">{branch.evidencePointer}</p>
<section className="discussion-panel__provenance" aria-label="answer provenance">
<span>Evidence</span>
<p>{branch.evidencePointer}</p>
</section>
<p className="discussion-panel__summary">{branch.summary}</p>
{branch.question && (
{hasQuestion && (
<section className="discussion-panel__qna" aria-label="defense question">
<p className="discussion-panel__question">{branch.question}</p>
{branch.shortAnswer && (
<p className="discussion-panel__short-answer">{branch.shortAnswer}</p>
<article className="discussion-panel__answer-card" aria-label="short defense answer">
<span>Short answer</span>
<p>{branch.shortAnswer}</p>
</article>
)}
{branch.expandedAnswer && (
<p className="discussion-panel__expanded-answer">{branch.expandedAnswer}</p>
<article className="discussion-panel__answer-card discussion-panel__answer-card--expanded" aria-label="answer expansion">
<span>Expanded answer</span>
<p>{branch.expandedAnswer}</p>
</article>
)}
{branch.speakerHint && (
<p className="discussion-panel__presenter-note" aria-label="presenter note">
<aside className="discussion-panel__presenter-note" aria-label="presenter note">
<span>Presenter note</span>
{branch.speakerHint}
</p>
<p>{branch.speakerHint}</p>
</aside>
)}
</section>
)}
{branch.detail && (
<p className="discussion-panel__detail">
{branch.detail.links?.map((link, index) => (
<span key={link.href}>
{index > 0 && " · "}
<a href={link.href} target="_blank" rel="noopener noreferrer">{link.label}</a>
</span>
))}
{branch.detail.links && branch.detail.links.length > 0 ? " — " : ""}
{branch.detail.text}
</p>
<section className="discussion-panel__detail" aria-label="additional context">
<p>
{branch.detail.links?.map((link, index) => (
<span key={link.href}>
{index > 0 && " · "}
<a href={link.href} target="_blank" rel="noopener noreferrer">{link.label}</a>
</span>
))}
{branch.detail.links && branch.detail.links.length > 0 ? " — " : ""}
{branch.detail.text}
</p>
</section>
)}
<button ref={returnButtonRef} type="button" onClick={onClose} className="discussion-panel__return">
Return to {parentScene?.title ?? "scene"}
@@ -593,9 +593,26 @@
letter-spacing: 0.05em;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__evidence {
font-size: 0.8rem;
color: var(--color-editorial-muted, oklch(0.48 0.025 65));
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__provenance {
display: grid;
gap: 0.2rem;
margin: 0.55rem 0 0;
border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 24%, transparent);
border-radius: 0.6rem;
padding: 0.5rem 0.6rem;
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 82%, white);
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__provenance span,
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__answer-card span {
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 68%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
font: 700 0.68rem/1 var(--font-interface);
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__provenance p {
margin: 0;
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 84%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
font-size: 0.82rem;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__summary {
@@ -605,58 +622,79 @@
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__qna {
display: grid;
gap: 0.6rem;
margin: 0.75rem 0;
padding: 0.85rem;
border: 1px solid color-mix(in oklch, var(--color-intent, oklch(0.53 0.17 250)) 28%, transparent);
border-radius: 1rem;
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 74%, white);
grid-template-columns: minmax(0, 1.1fr) minmax(14rem, 0.9fr);
gap: 0.7rem;
margin: 0.85rem 0;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__question,
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__short-answer {
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__question {
grid-column: 1 / -1;
margin: 0;
font-size: 1.02rem;
font-weight: 750;
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
font-size: 1.15rem;
font-weight: 760;
line-height: 1.15;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__short-answer {
font-weight: 400;
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__answer-card {
display: grid;
gap: 0.35rem;
border: 1px solid color-mix(in oklch, var(--color-intent, oklch(0.53 0.17 250)) 26%, transparent);
border-radius: 0.75rem;
padding: 0.7rem;
background: color-mix(in oklch, var(--color-intent, oklch(0.53 0.17 250)) 6%, var(--color-editorial-paper, oklch(0.975 0.012 82)));
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__expanded-answer {
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__answer-card--expanded {
border-color: color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 28%, transparent);
background: color-mix(in oklch, var(--color-editorial-paper, oklch(0.975 0.012 82)) 90%, white);
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__answer-card p {
margin: 0;
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
line-height: 1.45;
color: var(--color-editorial-ink, oklch(0.19 0.015 65));
line-height: 1.42;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__presenter-note {
display: grid;
gap: 0.3rem;
margin: 0;
padding: 0.55rem 0.65rem;
border: 1px dashed color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 38%, transparent);
border-radius: 0.55rem;
background: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 10%, var(--color-editorial-paper, oklch(0.975 0.012 82)));
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 76%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
font-size: 0.82rem;
line-height: 1.35;
border: 1px dashed color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 42%, transparent);
border-radius: 0.75rem;
padding: 0.7rem;
background: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 9%, var(--color-editorial-paper, oklch(0.975 0.012 82)));
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__presenter-note span {
display: block;
margin-bottom: 0.2rem;
color: color-mix(in oklch, var(--color-human, oklch(0.68 0.17 55)) 70%, var(--color-editorial-ink, oklch(0.19 0.015 65)));
font: 750 0.64rem/1 var(--font-mono, monospace);
letter-spacing: 0.08em;
text-transform: uppercase;
font: 700 0.68rem/1 var(--font-interface);
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__presenter-note p {
margin: 0;
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 84%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
font-size: 0.84rem;
line-height: 1.35;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__detail {
font-size: 0.85rem;
margin: 0.65rem 0 0;
border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 24%, transparent);
border-radius: 0.65rem;
padding: 0.6rem;
color: color-mix(in oklch, var(--color-editorial-ink, oklch(0.19 0.015 65)) 82%, var(--color-editorial-muted, oklch(0.48 0.025 65)));
border-left: 2px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 42%, transparent);
padding-left: 0.65rem;
margin: 0.5rem 0;
font-size: 0.85rem;
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__detail p {
margin: 0;
}
@media (max-height: 760px) {
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__qna {
grid-template-columns: minmax(0, 1fr);
}
}
.discussion-panel[data-presentation-surface="editorial"] .discussion-panel__return {