fix: make presentation figures inspectable
This commit is contained in:
@@ -186,6 +186,24 @@ describe("InteractiveFigure", () => {
|
||||
expect(figure.querySelector(".interactive-figure__canvas")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("keeps root stage figures in presentation mode", () => {
|
||||
renderFigure({ focusPath: [], size: "stage" });
|
||||
|
||||
expect(screen.getByRole("group", { name: /architecture/i })).toHaveAttribute(
|
||||
"data-pan-zoom",
|
||||
"disabled",
|
||||
);
|
||||
});
|
||||
|
||||
it("enables pan and zoom inspection for focused stage figures", () => {
|
||||
renderFigure({ focusPath: ["runtime"], size: "stage" });
|
||||
|
||||
expect(screen.getByRole("group", { name: /runtime detail/i })).toHaveAttribute(
|
||||
"data-pan-zoom",
|
||||
"enabled",
|
||||
);
|
||||
});
|
||||
|
||||
it("resets roving focus when focusPath changes", () => {
|
||||
const { rerender } = render(
|
||||
<InteractiveFigure
|
||||
|
||||
@@ -83,9 +83,8 @@ const FitViewOnLayoutChange = ({ layoutKey }: { layoutKey: string }) => {
|
||||
const { fitView } = useReactFlow();
|
||||
useEffect(() => {
|
||||
void fitView({ padding: 0.15, duration: 0 });
|
||||
// React Flow can measure before the scaled presentation canvas and
|
||||
// breadcrumb row settle. Fit again on the next frame to align edges with
|
||||
// the final node boxes without adding a larger measurement framework.
|
||||
// React Flow can measure before the breadcrumb row and stage grid settle.
|
||||
// Fit again on the next frame to align edges with the final node boxes.
|
||||
const frame = window.requestAnimationFrame(() => {
|
||||
void fitView({ padding: 0.15, duration: 0 });
|
||||
});
|
||||
@@ -111,6 +110,7 @@ const InteractiveFigureInner = ({
|
||||
const initialFocusedNodeId = activeNodeId ?? focus.figure.nodes[0]?.id ?? "";
|
||||
const [focusedNodeId, setFocusedNodeId] = useState(initialFocusedNodeId);
|
||||
const focusedNodeIdRef = useRef(initialFocusedNodeId);
|
||||
const graphInspectionEnabled = size === "stage" && focus.path.length > 0;
|
||||
|
||||
const fallbackFocusedNodeId = activeNodeId ?? focus.figure.nodes[0]?.id ?? "";
|
||||
useEffect(() => {
|
||||
@@ -230,6 +230,7 @@ const InteractiveFigureInner = ({
|
||||
data-motion={motionDisabled ? "disabled" : "enabled"}
|
||||
data-figure-id={focus.figure.id}
|
||||
data-figure-size={size}
|
||||
data-pan-zoom={graphInspectionEnabled ? "enabled" : "disabled"}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<FigureBreadcrumbs
|
||||
@@ -248,11 +249,13 @@ const InteractiveFigureInner = ({
|
||||
nodesFocusable={false}
|
||||
edgesFocusable={false}
|
||||
elementsSelectable={false}
|
||||
panOnDrag={false}
|
||||
zoomOnScroll={false}
|
||||
zoomOnPinch={false}
|
||||
zoomOnDoubleClick={false}
|
||||
preventScrolling={false}
|
||||
minZoom={0.35}
|
||||
maxZoom={2.2}
|
||||
panOnDrag={graphInspectionEnabled}
|
||||
zoomOnScroll={graphInspectionEnabled}
|
||||
zoomOnPinch={graphInspectionEnabled}
|
||||
zoomOnDoubleClick={graphInspectionEnabled}
|
||||
preventScrolling={graphInspectionEnabled}
|
||||
onNodeClick={handleNodeClick}
|
||||
>
|
||||
<FitViewOnLayoutChange layoutKey={focus.figure.id} />
|
||||
|
||||
@@ -32,10 +32,23 @@
|
||||
background: color-mix(in oklch, var(--color-editorial-surface, oklch(0.96 0.012 82)) 92%, white);
|
||||
}
|
||||
|
||||
.interactive-figure .react-flow__pane {
|
||||
/*
|
||||
Presentation overview figures should not steal normal slide navigation
|
||||
gestures. Focused stage figures opt into React Flow inspection, where the pane
|
||||
needs pointer events for drag-pan and wheel zoom.
|
||||
*/
|
||||
.interactive-figure[data-pan-zoom="disabled"] .react-flow__pane {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.interactive-figure[data-pan-zoom="enabled"] .react-flow__pane {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.interactive-figure[data-pan-zoom="enabled"] .react-flow__pane:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.interactive-figure .react-flow__node {
|
||||
cursor: default;
|
||||
}
|
||||
@@ -133,8 +146,10 @@
|
||||
}
|
||||
|
||||
.interactive-figure[data-figure-size="stage"] .interactive-figure__canvas {
|
||||
min-width: 1440px;
|
||||
min-height: 470px;
|
||||
position: relative;
|
||||
min-width: 100%;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.interactive-figure[data-figure-size="stage"] .react-flow {
|
||||
|
||||
@@ -23,4 +23,16 @@ describe("interactive-figure CSS", () => {
|
||||
// Only the stage variant should have gradients.
|
||||
expect(totalGradientSelectors).toBe(stageGradients?.length ?? 0);
|
||||
});
|
||||
|
||||
it("does not force stage figures wider than the visible canvas", () => {
|
||||
expect(css).not.toContain("min-width: 1440px");
|
||||
expect(css).toContain('data-figure-size="stage"] .interactive-figure__canvas');
|
||||
expect(css).toContain("min-width: 100%");
|
||||
});
|
||||
|
||||
it("lets stage figures shrink to the available scene height", () => {
|
||||
expect(css).not.toContain("min-height: 470px");
|
||||
expect(css).toContain("min-height: 0");
|
||||
expect(css).toContain("height: 100%");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user