mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-04-23 02:34:48 -05:00
5babd09679
* improve overall docs structure and things
290 lines
7.5 KiB
TypeScript
290 lines
7.5 KiB
TypeScript
import React from "react";
|
|
import { brand, state, fill, inactive, gradient } from "./diagram-colors";
|
|
|
|
const WorkflowDiagram: React.FC = () => {
|
|
const nodeW = 130;
|
|
const nodeH = 46;
|
|
const rx = 10;
|
|
|
|
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 720 260"
|
|
className="w-full h-auto"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<defs>
|
|
<linearGradient id="wf-blue" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop
|
|
offset="0%"
|
|
stopColor={gradient.blue[0]}
|
|
stopOpacity="0.6"
|
|
/>
|
|
<stop
|
|
offset="100%"
|
|
stopColor={gradient.blue[1]}
|
|
stopOpacity="0.3"
|
|
/>
|
|
</linearGradient>
|
|
<linearGradient id="wf-magenta" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop
|
|
offset="0%"
|
|
stopColor={gradient.magenta[0]}
|
|
stopOpacity="0.6"
|
|
/>
|
|
<stop
|
|
offset="100%"
|
|
stopColor={gradient.magenta[1]}
|
|
stopOpacity="0.3"
|
|
/>
|
|
</linearGradient>
|
|
<linearGradient id="wf-green" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop
|
|
offset="0%"
|
|
stopColor={gradient.green[0]}
|
|
stopOpacity="0.6"
|
|
/>
|
|
<stop
|
|
offset="100%"
|
|
stopColor={gradient.green[1]}
|
|
stopOpacity="0.3"
|
|
/>
|
|
</linearGradient>
|
|
</defs>
|
|
|
|
<style>{`
|
|
@keyframes wf-dash {
|
|
to { stroke-dashoffset: -20; }
|
|
}
|
|
.wf-flow {
|
|
stroke-dasharray: 8 6;
|
|
animation: wf-dash 0.8s linear infinite;
|
|
}
|
|
`}</style>
|
|
|
|
{/* Workflow label */}
|
|
<text
|
|
x="360"
|
|
y="24"
|
|
textAnchor="middle"
|
|
fill={brand.cyanDark}
|
|
fontSize="11"
|
|
fontWeight="500"
|
|
letterSpacing="0.05em"
|
|
>
|
|
WORKFLOW
|
|
</text>
|
|
|
|
{/* Dashed container */}
|
|
<rect
|
|
x="10"
|
|
y="34"
|
|
width="700"
|
|
height="216"
|
|
rx="14"
|
|
fill="none"
|
|
stroke={inactive.edge}
|
|
strokeWidth="1"
|
|
strokeDasharray="6 4"
|
|
/>
|
|
|
|
{/* --- Row 1: Task A → Task B --- */}
|
|
{/* Task A */}
|
|
<rect
|
|
x={40}
|
|
y={60}
|
|
width={nodeW}
|
|
height={nodeH}
|
|
rx={rx}
|
|
fill={fill.activeNode}
|
|
stroke="url(#wf-blue)"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<text
|
|
x={40 + nodeW / 2}
|
|
y={60 + nodeH / 2 + 1}
|
|
textAnchor="middle"
|
|
fill={brand.cyan}
|
|
fontSize="12"
|
|
fontWeight="500"
|
|
>
|
|
Task A
|
|
</text>
|
|
|
|
{/* Edge A → B */}
|
|
<path
|
|
d={`M ${40 + nodeW + 2} ${60 + nodeH / 2} L ${248} ${60 + nodeH / 2}`}
|
|
fill="none"
|
|
stroke={brand.blue}
|
|
strokeWidth="2"
|
|
className="wf-flow"
|
|
/>
|
|
|
|
{/* Task B */}
|
|
<rect
|
|
x={250}
|
|
y={60}
|
|
width={nodeW}
|
|
height={nodeH}
|
|
rx={rx}
|
|
fill={fill.activeNode}
|
|
stroke="url(#wf-blue)"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<text
|
|
x={250 + nodeW / 2}
|
|
y={60 + nodeH / 2 + 1}
|
|
textAnchor="middle"
|
|
fill={brand.cyan}
|
|
fontSize="12"
|
|
fontWeight="500"
|
|
>
|
|
Task B
|
|
</text>
|
|
|
|
{/* --- Fan out: B → C and B → D --- */}
|
|
{/* Edge B → C */}
|
|
<path
|
|
d={`M ${250 + nodeW + 2} ${60 + nodeH / 2} C ${430} ${60 + nodeH / 2}, ${430} ${60 + nodeH / 2}, ${460} ${60 + nodeH / 2}`}
|
|
fill="none"
|
|
stroke={brand.magenta}
|
|
strokeWidth="2"
|
|
className="wf-flow"
|
|
style={{ animationDelay: "0.2s" }}
|
|
/>
|
|
|
|
{/* Edge B → D */}
|
|
<path
|
|
d={`M ${250 + nodeW + 2} ${60 + nodeH / 2} C ${420} ${60 + nodeH / 2}, ${420} ${170 + nodeH / 2}, ${460} ${170 + nodeH / 2}`}
|
|
fill="none"
|
|
stroke={brand.magenta}
|
|
strokeWidth="2"
|
|
className="wf-flow"
|
|
style={{ animationDelay: "0.3s" }}
|
|
/>
|
|
|
|
{/* Task C */}
|
|
<rect
|
|
x={460}
|
|
y={60}
|
|
width={nodeW}
|
|
height={nodeH}
|
|
rx={rx}
|
|
fill={fill.magenta}
|
|
stroke="url(#wf-magenta)"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<text
|
|
x={460 + nodeW / 2}
|
|
y={60 + nodeH / 2 + 1}
|
|
textAnchor="middle"
|
|
fill={brand.magentaLight}
|
|
fontSize="12"
|
|
fontWeight="500"
|
|
>
|
|
Task C
|
|
</text>
|
|
|
|
{/* Task D */}
|
|
<rect
|
|
x={460}
|
|
y={170}
|
|
width={nodeW}
|
|
height={nodeH}
|
|
rx={rx}
|
|
fill={fill.magenta}
|
|
stroke="url(#wf-magenta)"
|
|
strokeWidth="1.5"
|
|
/>
|
|
<text
|
|
x={460 + nodeW / 2}
|
|
y={170 + nodeH / 2 + 1}
|
|
textAnchor="middle"
|
|
fill={brand.magentaLight}
|
|
fontSize="12"
|
|
fontWeight="500"
|
|
>
|
|
Task D
|
|
</text>
|
|
|
|
{/* --- Both converge to Result --- */}
|
|
{/* Edges C → Result, D → Result drawn before Result box so they don't overlap text */}
|
|
|
|
{/* Annotations */}
|
|
<text
|
|
x={40 + nodeW / 2}
|
|
y={60 + nodeH + 16}
|
|
textAnchor="middle"
|
|
fill={brand.blue}
|
|
fontSize="9"
|
|
>
|
|
start
|
|
</text>
|
|
<text
|
|
x={315}
|
|
y={60 + nodeH + 16}
|
|
textAnchor="middle"
|
|
fill={brand.blue}
|
|
fontSize="9"
|
|
>
|
|
depends on A
|
|
</text>
|
|
<text
|
|
x={525}
|
|
y={60 + nodeH + 16}
|
|
textAnchor="middle"
|
|
fill={brand.magenta}
|
|
fontSize="9"
|
|
>
|
|
parallel
|
|
</text>
|
|
<text
|
|
x={525}
|
|
y={170 + nodeH + 16}
|
|
textAnchor="middle"
|
|
fill={brand.magenta}
|
|
fontSize="9"
|
|
>
|
|
parallel
|
|
</text>
|
|
|
|
{/* Vertical dashed line between sequential and parallel sections */}
|
|
<line
|
|
x1="430"
|
|
y1="50"
|
|
x2="430"
|
|
y2="240"
|
|
stroke={inactive.edge}
|
|
strokeWidth="1"
|
|
strokeDasharray="4 4"
|
|
opacity="0.5"
|
|
/>
|
|
<text
|
|
x="432"
|
|
y="248"
|
|
fill={inactive.text}
|
|
fontSize="8"
|
|
textAnchor="start"
|
|
>
|
|
fan-out
|
|
</text>
|
|
|
|
{/* Labels for sections */}
|
|
<text
|
|
x="200"
|
|
y="248"
|
|
fill={inactive.text}
|
|
fontSize="8"
|
|
textAnchor="middle"
|
|
>
|
|
sequential
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default WorkflowDiagram;
|