summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/directives/StepNode.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-09 00:11:51 +0000
committersoryu <soryu@soryu.co>2026-02-09 00:11:51 +0000
commit8c23b3ab6f7fabca01b0468911bae073aa5ced32 (patch)
treef50159aee13b13f0b55618ac09e9be1f89a41bb2 /makima/frontend/src/components/directives/StepNode.tsx
parent3662b334dfd68cfdf00ed44ae88927c2e1b2aabe (diff)
downloadsoryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.tar.gz
soryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.zip
Add new directive mechanism v3
Diffstat (limited to 'makima/frontend/src/components/directives/StepNode.tsx')
-rw-r--r--makima/frontend/src/components/directives/StepNode.tsx82
1 files changed, 82 insertions, 0 deletions
diff --git a/makima/frontend/src/components/directives/StepNode.tsx b/makima/frontend/src/components/directives/StepNode.tsx
new file mode 100644
index 0000000..fa91956
--- /dev/null
+++ b/makima/frontend/src/components/directives/StepNode.tsx
@@ -0,0 +1,82 @@
+import type { DirectiveStep, StepStatus } from "../../lib/api";
+
+const STATUS_COLORS: Record<StepStatus, { bg: string; border: string; text: string }> = {
+ pending: { bg: "bg-[#1a2540]", border: "border-[#2a3a5a]", text: "text-[#7788aa]" },
+ ready: { bg: "bg-[#2a2a10]", border: "border-[#4a4a20]", text: "text-yellow-400" },
+ running: { bg: "bg-[#0a2a1a]", border: "border-[#1a5a3a]", text: "text-green-400" },
+ completed: { bg: "bg-[#0a2a2a]", border: "border-[#1a5a5a]", text: "text-emerald-400" },
+ failed: { bg: "bg-[#2a1a1a]", border: "border-[#5a2a2a]", text: "text-red-400" },
+ skipped: { bg: "bg-[#1a1a2a]", border: "border-[#2a2a4a]", text: "text-[#7788aa]" },
+};
+
+const STATUS_LABELS: Record<StepStatus, string> = {
+ pending: "PENDING",
+ ready: "READY",
+ running: "RUNNING",
+ completed: "DONE",
+ failed: "FAILED",
+ skipped: "SKIP",
+};
+
+interface StepNodeProps {
+ step: DirectiveStep;
+ onComplete?: () => void;
+ onFail?: () => void;
+ onSkip?: () => void;
+}
+
+export function StepNode({ step, onComplete, onFail, onSkip }: StepNodeProps) {
+ const colors = STATUS_COLORS[step.status] || STATUS_COLORS.pending;
+ const label = STATUS_LABELS[step.status] || step.status.toUpperCase();
+
+ return (
+ <div
+ className={`${colors.bg} ${colors.border} border rounded px-3 py-2 min-w-[160px] max-w-[220px]`}
+ >
+ <div className="flex items-center justify-between gap-2 mb-1">
+ <span className="text-[11px] font-mono text-white truncate font-medium">
+ {step.name}
+ </span>
+ <span className={`text-[9px] font-mono ${colors.text} uppercase shrink-0`}>
+ {label}
+ </span>
+ </div>
+ {step.description && (
+ <p className="text-[10px] text-[#7788aa] font-mono truncate mb-1">
+ {step.description}
+ </p>
+ )}
+ {(step.status === "running" || step.status === "ready") && (
+ <div className="flex gap-1 mt-1">
+ {onComplete && (
+ <button
+ type="button"
+ onClick={onComplete}
+ className="text-[9px] font-mono text-emerald-400 hover:text-emerald-300 bg-transparent border border-emerald-800 rounded px-1.5 py-0.5"
+ >
+ Done
+ </button>
+ )}
+ {onFail && (
+ <button
+ type="button"
+ onClick={onFail}
+ className="text-[9px] font-mono text-red-400 hover:text-red-300 bg-transparent border border-red-800 rounded px-1.5 py-0.5"
+ >
+ Fail
+ </button>
+ )}
+ {onSkip && (
+ <button
+ type="button"
+ onClick={onSkip}
+ className="text-[9px] font-mono text-[#7788aa] hover:text-white bg-transparent border border-[#2a3a5a] rounded px-1.5 py-0.5"
+ >
+ Skip
+ </button>
+ )}
+ </div>
+ )}
+ </div>
+ );
+}