Files
hatchet/frontend/docs/components/FanoutDiagram.tsx
T
Gabe Ruttner 5babd09679 docs: chunky overhaul (#3129)
* improve overall docs structure and things
2026-03-04 14:33:15 -08:00

231 lines
6.1 KiB
TypeScript

import React from "react";
import { brand, state, fill, inactive, gradient } from "./diagram-colors";
const FanoutDiagram: React.FC = () => {
const childYPositions = [40, 110, 180, 270];
const childLabels = ["Child 1", "Child 2", "Child 3", "Child N"];
return (
<div className="my-8 flex justify-center">
<div className="w-full max-w-3xl rounded-xl border border-neutral-700/40 bg-neutral-900/30 p-6 backdrop-blur-sm">
<svg
viewBox="0 0 800 330"
className="w-full h-auto"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="blue-grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop
offset="0%"
stopColor="rgb(51, 146, 255)"
stopOpacity="0.6"
/>
<stop
offset="100%"
stopColor="rgb(133, 189, 255)"
stopOpacity="0.3"
/>
</linearGradient>
<linearGradient
id="magenta-grad"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop
offset="0%"
stopColor="rgb(188, 70, 221)"
stopOpacity="0.6"
/>
<stop
offset="100%"
stopColor="rgb(213, 133, 239)"
stopOpacity="0.3"
/>
</linearGradient>
<linearGradient id="green-grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop
offset="0%"
stopColor="rgb(34, 197, 94)"
stopOpacity="0.6"
/>
<stop
offset="100%"
stopColor="rgb(74, 222, 128)"
stopOpacity="0.3"
/>
</linearGradient>
</defs>
<style>{`
@keyframes dash {
to { stroke-dashoffset: -20; }
}
.flow-line-out {
stroke-dasharray: 8 6;
animation: dash 0.8s linear infinite;
}
.flow-line-in {
stroke-dasharray: 8 6;
animation: dash 0.8s linear infinite;
}
`}</style>
{/* Parent Task Box */}
<rect
x="20"
y="125"
width="170"
height="80"
rx="12"
fill="rgba(10, 16, 41, 0.3)"
stroke="url(#blue-grad)"
strokeWidth="2"
/>
<text
x="105"
y="160"
textAnchor="middle"
fill="#B8D9FF"
fontSize="14"
fontWeight="600"
>
Parent Task
</text>
<text
x="105"
y="180"
textAnchor="middle"
fill="#3392FF"
fontSize="11"
>
spawn(input)
</text>
{/* Fan-out lines from parent to children */}
{childYPositions.map((cy, i) => (
<path
key={`out-${i}`}
d={`M 190 165 C 260 165, 260 ${cy + 25}, 320 ${cy + 25}`}
fill="none"
stroke="rgb(51, 146, 255)"
strokeWidth="1.5"
strokeOpacity="0.7"
className="flow-line-out"
style={{ animationDelay: `${i * 0.15}s` }}
/>
))}
{/* Child boxes */}
{childLabels.slice(0, 3).map((label, i) => (
<g key={label}>
<rect
x="320"
y={childYPositions[i]}
width="150"
height="50"
rx="10"
fill="rgba(188, 70, 221, 0.2)"
stroke="url(#magenta-grad)"
strokeWidth="1.5"
/>
<text
x="395"
y={childYPositions[i] + 30}
textAnchor="middle"
fill="#D585EF"
fontSize="12"
fontWeight="500"
>
{label}
</text>
</g>
))}
{/* Ellipsis between Child 3 and Child N */}
<text
x="395"
y="255"
textAnchor="middle"
fill="#64748B"
fontSize="18"
fontWeight="bold"
>
...
</text>
{/* Child N */}
<rect
x="320"
y={childYPositions[3]}
width="150"
height="50"
rx="10"
fill="rgba(188, 70, 221, 0.2)"
stroke="url(#magenta-grad)"
strokeWidth="1.5"
/>
<text
x="395"
y={childYPositions[3] + 30}
textAnchor="middle"
fill="#D585EF"
fontSize="12"
fontWeight="500"
>
Child N
</text>
{/* Converge lines from children to results */}
{childYPositions.map((cy, i) => (
<path
key={`in-${i}`}
d={`M 470 ${cy + 25} C 540 ${cy + 25}, 540 165, 600 165`}
fill="none"
stroke="rgb(34, 197, 94)"
strokeWidth="1.5"
strokeOpacity="0.7"
className="flow-line-in"
style={{ animationDelay: `${i * 0.15 + 0.4}s` }}
/>
))}
{/* Results Box */}
<rect
x="600"
y="125"
width="180"
height="80"
rx="12"
fill="rgba(34, 197, 94, 0.3)"
stroke="url(#green-grad)"
strokeWidth="2"
/>
<text
x="690"
y="160"
textAnchor="middle"
fill="#86EFAC"
fontSize="14"
fontWeight="600"
>
Collect Results
</text>
<text
x="690"
y="180"
textAnchor="middle"
fill="#4ADE80"
fontSize="11"
>
await all children
</text>
</svg>
</div>
</div>
);
};
export default FanoutDiagram;