File
Blob: src/client/components/step-row.tsx
| 1 | import type { RunStep } from "@/contracts"; |
| 2 | import { StatusPill } from "@/client/components/status-pill"; |
| 3 | import { formatDuration } from "@/client/lib"; |
| 4 | |
| 5 | const StepRow = ({ step, isActive }: { step: RunStep; isActive: boolean }) => { |
| 6 | return ( |
| 7 | <div |
| 8 | className={[ |
| 9 | "flex items-center gap-3 rounded-xl border p-3", |
| 10 | isActive ? "border-amber-500/30 bg-amber-500/5" : "border-zinc-800/60 bg-zinc-950/40", |
| 11 | ].join(" ")} |
| 12 | > |
| 13 | <span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-zinc-700/60 bg-zinc-800/60 text-xs font-medium text-zinc-400"> |
| 14 | {step.position} |
| 15 | </span> |
| 16 | <div className="min-w-0 flex-1"> |
| 17 | <div className="flex items-center gap-2"> |
| 18 | <span className="text-sm font-medium text-zinc-200">{step.name}</span> |
| 19 | <StatusPill status={step.status} /> |
| 20 | </div> |
| 21 | <p className="mt-0.5 truncate font-mono text-xs text-zinc-500">{step.command}</p> |
| 22 | <div className="mt-1 flex flex-wrap items-center gap-x-3 text-xs text-zinc-500"> |
| 23 | {step.startedAt && step.finishedAt ? <span>{formatDuration(step.startedAt, step.finishedAt)}</span> : null} |
| 24 | {step.exitCode !== null ? <span>exit {step.exitCode}</span> : null} |
| 25 | </div> |
| 26 | </div> |
| 27 | </div> |
| 28 | ); |
| 29 | }; |
| 30 | |
| 31 | export { StepRow }; |