fix: make architecture semantic zoom readable

This commit is contained in:
lda
2026-07-11 09:20:17 +07:00 Verified
parent 5e17d3e0c0
commit 833553c1d4
5 changed files with 21 additions and 1 deletions
@@ -186,6 +186,8 @@ describe("InteractiveFigure", () => {
renderFigure({ focusPath: [], size: "stage" });
const figure = screen.getByRole("group", { name: /architecture/i });
expect(figure).toHaveAttribute("data-figure-size", "stage");
expect(figure).toHaveAttribute("data-figure-layout", "layered");
expect(figure).toHaveAttribute("data-figure-focus-level", "0");
expect(figure.querySelector(".interactive-figure__canvas")).toBeInTheDocument();
});
@@ -205,6 +207,7 @@ describe("InteractiveFigure", () => {
"data-pan-zoom",
"enabled",
);
expect(screen.getByRole("group", { name: /runtime detail/i })).toHaveAttribute("data-figure-focus-level", "1");
});
it("resets roving focus when focusPath changes", () => {
@@ -230,6 +230,8 @@ const InteractiveFigureInner = ({
data-motion={motionDisabled ? "disabled" : "enabled"}
data-figure-id={focus.figure.id}
data-figure-size={size}
data-figure-layout={focus.figure.layout.kind}
data-figure-focus-level={focus.path.length}
data-pan-zoom={graphInspectionEnabled ? "enabled" : "disabled"}
onKeyDown={handleKeyDown}
>
@@ -237,6 +239,8 @@ const InteractiveFigureInner = ({
breadcrumbs={focus.breadcrumbs}
onNavigate={handleBreadcrumbNavigate}
/>
{/* React Flow must measure nodes in its unscaled coordinate space. Keep
this canvas responsive instead of reintroducing a CSS scale wrapper. */}
<div className="interactive-figure__canvas" ref={containerRef}>
<ReactFlow
nodes={rfNodes}
@@ -151,6 +151,10 @@
height: 100%;
}
.interactive-figure[data-figure-size="stage"][data-figure-layout="flow"] .interactive-figure__canvas {
min-width: 72rem;
}
.interactive-figure[data-figure-size="stage"] .react-flow {
border: 1px solid color-mix(in oklch, var(--color-editorial-muted, oklch(0.48 0.025 65)) 42%, transparent);
border-radius: 0.65rem;
@@ -85,6 +85,7 @@ describe("ArchitectureScene", () => {
renderArchitecture({ focusPath: [] });
expect(screen.getByRole("group", { name: /architecture/i })).toHaveAttribute("data-figure-size", "stage");
expect(screen.getByTestId("architecture-scene")).toHaveAttribute("data-visual-pass", "architecture-stage");
expect(screen.getByTestId("architecture-scene")).toHaveAttribute("data-architecture-focus", "system");
});
it("renders a directly linked nested provider view", () => {
@@ -94,5 +95,7 @@ describe("ArchitectureScene", () => {
expect(screen.getByRole("group", { name: /configured providers/i })).toBeInTheDocument();
expect(screen.getByText("MCP sources")).toBeInTheDocument();
expect(screen.getByText("Python sources")).toBeInTheDocument();
expect(screen.getByTestId("architecture-scene")).toHaveAttribute("data-architecture-focus", "nested");
expect(screen.getByRole("group", { name: /configured providers/i })).toHaveAttribute("data-figure-focus-level", "2");
});
});
@@ -31,7 +31,13 @@ export const ArchitectureScene = ({
: architectureCatalog;
return (
<section className="architecture-scene" data-testid="architecture-scene" data-visual-pass="architecture-stage">
<section
className="architecture-scene"
data-testid="architecture-scene"
data-visual-pass="architecture-stage"
data-focus-level={focusPath.length}
data-architecture-focus={focusPath.length === 0 ? "system" : "nested"}
>
<StageCaption eyebrow={`Act II · ${scene.claimClass}`} title={scene.title}>
<p>{beat.caption}</p>
</StageCaption>