feat: mark presentation demo surface hierarchy

This commit is contained in:
lda
2026-07-10 04:16:06 +07:00 Verified
parent 942c64a8cb
commit 99f933188f
4 changed files with 46 additions and 1 deletions
@@ -231,4 +231,28 @@ describe("DemoWorkflowScene", () => {
renderBeat("trace", "resume-output-evidence");
expect(screen.getByRole("region", { name: /current product moment/i })).toHaveAttribute("data-moment", "trace");
});
it("marks graph beats with one primary workflow graph and one run receipt support surface", () => {
renderBeat("graph");
const stage = screen.getByLabelText(/demo workflow stage/i);
expect(stage).toHaveAttribute("data-primary-surface", "workflow-graph");
expect(stage).toHaveAttribute("data-support-surface", "run-receipt");
});
it("marks approval beats as interrupt approval with facts-only support", () => {
renderBeat("approval", "typed-human-boundary");
const stage = screen.getByLabelText(/demo workflow stage/i);
expect(stage).toHaveAttribute("data-primary-surface", "interrupt-approval");
expect(stage).toHaveAttribute("data-support-surface", "facts-only");
});
it("marks trace beats as trace evidence with output summary support", () => {
renderBeat("trace", "resume-output-evidence");
const stage = screen.getByLabelText(/demo workflow stage/i);
expect(stage).toHaveAttribute("data-primary-surface", "trace-evidence");
expect(stage).toHaveAttribute("data-support-surface", "output-summary");
});
});
@@ -8,6 +8,7 @@ import {
} from "./demo-workflow-model.js";
import { projectDemoRunFacts } from "./demo-run-facts.js";
import type { DemoApprovalActions } from "./demo-approval-actions.js";
import { demoSurfaceForBeat } from "./presentation-coherence.js";
import { DemoContinuityRail } from "./DemoContinuityRail.js";
import { DemoOutcomePanel } from "./DemoOutcomePanel.js";
import { GuidedProductMoment } from "./GuidedProductMoment.js";
@@ -81,6 +82,7 @@ export const DemoWorkflowScene = ({
const lens = demoBeatLensForBeat(beat.id);
const currentOperation = currentEvent ? projectOperationPresentation(currentEvent) : null;
const facts = projectDemoRunFacts(demo);
const surface = demoSurfaceForBeat(scene.id, beat.id);
const showOutcomePanel = beat.id === "resume" || beat.id === "output" || beat.id === "trace";
const showExpandedOperation = beat.id === "operation" || beat.id === "resume" || beat.id === "trace";
@@ -103,7 +105,14 @@ export const DemoWorkflowScene = ({
<DemoContinuityRail lens={lens} />
<div className="demo-workflow-stage" data-beat={beat.id} data-demo-layout={layout} aria-label="demo workflow stage">
<div
className="demo-workflow-stage"
data-beat={beat.id}
data-demo-layout={layout}
data-primary-surface={surface.primarySurface}
data-support-surface={surface.supportSurface}
aria-label="demo workflow stage"
>
{isGuidedDemoMoment ? (
<GuidedProductMoment
beat={beat}
@@ -24,6 +24,7 @@ export const OperationBlock = ({
layoutId="workflow-start-operation"
transition={{ duration: 0.24, ease: [0.16, 1, 0.3, 1] }}
className="operation-receipt"
data-operation-variant={variant}
aria-label={`${operation.operation} execution receipt`}
>
<div className="operation-receipt__identity">
@@ -45,6 +46,7 @@ export const OperationBlock = ({
layoutId="workflow-start-operation"
transition={{ duration: 0.24, ease: [0.16, 1, 0.3, 1] }}
className="operation-block operation-block--expanded"
data-operation-variant={variant}
aria-label={`${operation.operation} operation`}
>
<header className="operation-block__header">
@@ -855,6 +855,16 @@
grid-template-columns: minmax(0, 1fr) minmax(16rem, 24%);
}
.demo-workflow-stage[data-support-surface="run-receipt"] .operation-block[data-operation-variant="receipt"],
.demo-workflow-stage[data-support-surface="output-summary"] .run-facts-card[data-output-priority="summary"] {
opacity: 0.86;
}
.demo-workflow-stage[data-primary-surface="interrupt-approval"] .guided-product-moment__header,
.demo-workflow-stage[data-primary-surface="trace-evidence"] .guided-product-moment__header {
border-color: color-mix(in oklch, var(--accent-cyan) 38%, var(--stage-line));
}
@container presentation-canvas (max-width: 1050px) {
.demo-workflow-stage:has(.demo-outcome-panel),
.demo-workflow-stage[data-demo-layout="approval"],