feat: add presentation problem visual
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { cleanup, render, screen, within } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { findBeat, findScene } from "../storyboard.js";
|
||||
import { ProblemLoopScene } from "./ProblemLoopScene.js";
|
||||
|
||||
const problemScene = findScene("problem")!;
|
||||
|
||||
afterEach(() => cleanup());
|
||||
|
||||
describe("ProblemLoopScene", () => {
|
||||
it("renders the action sequence as useful but insufficient", () => {
|
||||
render(<ProblemLoopScene scene={problemScene} beat={findBeat("problem", "direct-actions")!} />);
|
||||
|
||||
const action = screen.getByRole("group", { name: "Action sequence" });
|
||||
expect(within(action).getByText("think")).toBeInTheDocument();
|
||||
expect(within(action).getAllByText("tool")).toHaveLength(2);
|
||||
expect(within(action).getByText("observe")).toBeInTheDocument();
|
||||
expect(within(action).getByText("done")).toBeInTheDocument();
|
||||
expect(screen.getByText(/useful once/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders reusable automation with simple verbs only", () => {
|
||||
render(<ProblemLoopScene scene={problemScene} beat={findBeat("problem", "missing-contracts")!} />);
|
||||
|
||||
const automation = screen.getByRole("group", { name: "Reusable automation" });
|
||||
for (const label of ["design", "save", "connect", "run", "inspect"]) {
|
||||
expect(within(automation).getByText(label)).toBeInTheDocument();
|
||||
}
|
||||
for (const formalName of ["Draft", "Artifact", "Deployment", "Trace"]) {
|
||||
expect(screen.queryByText(formalName)).not.toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { StageCaption } from "../StageCaption.js";
|
||||
import type { SceneBeatDefinition, SceneDefinition } from "../storyboard.js";
|
||||
import { ConceptNode, ConceptRail } from "./ConceptPrimitives.js";
|
||||
|
||||
type ProblemLoopSceneProps = {
|
||||
readonly scene: SceneDefinition;
|
||||
readonly beat: SceneBeatDefinition;
|
||||
};
|
||||
|
||||
export const ProblemLoopScene = ({ scene, beat }: ProblemLoopSceneProps) => {
|
||||
const automationBeat = beat.id === "missing-contracts";
|
||||
return (
|
||||
<>
|
||||
<StageCaption eyebrow="Problem shape" title={scene.title}>
|
||||
<p>{beat.caption}</p>
|
||||
</StageCaption>
|
||||
<section className="problem-loop-scene" aria-label="action sequence versus reusable automation">
|
||||
<div className="problem-loop-scene__side" data-problem-active={automationBeat ? "false" : "true"}>
|
||||
<h2>Action sequence</h2>
|
||||
<ConceptRail label="Action sequence">
|
||||
<ConceptNode title="think" icon="think" emphasis={automationBeat ? "muted" : "normal"} />
|
||||
<ConceptNode title="tool" icon="toolCall" emphasis={automationBeat ? "muted" : "normal"} />
|
||||
<ConceptNode title="observe" icon="observe" emphasis={automationBeat ? "muted" : "normal"} />
|
||||
<ConceptNode title="tool" icon="toolCall" emphasis={automationBeat ? "muted" : "normal"} />
|
||||
<ConceptNode title="done" icon="done" emphasis={automationBeat ? "muted" : "normal"} />
|
||||
</ConceptRail>
|
||||
<p>Useful once. Hard to reuse.</p>
|
||||
</div>
|
||||
|
||||
<div className="problem-loop-scene__bridge" aria-hidden="true">→</div>
|
||||
|
||||
<div className="problem-loop-scene__side" data-problem-active={automationBeat ? "true" : "false"}>
|
||||
<h2>Reusable automation</h2>
|
||||
<ConceptRail label="Reusable automation">
|
||||
<ConceptNode title="design" icon="design" emphasis={automationBeat ? "primary" : "normal"} />
|
||||
<ConceptNode title="save" icon="save" emphasis={automationBeat ? "primary" : "normal"} />
|
||||
<ConceptNode title="connect" icon="connect" emphasis={automationBeat ? "primary" : "normal"} />
|
||||
<ConceptNode title="run" icon="run" emphasis={automationBeat ? "primary" : "normal"} />
|
||||
<ConceptNode title="inspect" icon="inspect" emphasis={automationBeat ? "primary" : "normal"} />
|
||||
</ConceptRail>
|
||||
<p>The platform makes work reusable.</p>
|
||||
</div>
|
||||
</section>
|
||||
<p className="scene-body__evidence">{scene.evidencePointer}</p>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user