37 lines · 1.3 KB
import { cn } from "~/utils/cn";
import type { StatusState } from "~/lib/types";
import { TONE_FILL, type Tone } from "~/ui/tones";

const STATUS_STYLES: Record<string, { tone: Tone; pulse?: boolean; label: string }> = {
  success: { tone: "success", label: "Passing" },
  failure: { tone: "danger", label: "Failing" },
  error: { tone: "danger", label: "Errored" },
  pending: { tone: "warning", pulse: true, label: "Pending" },
  in_progress: { tone: "warning", pulse: true, label: "Running" },
  queued: { tone: "neutral", pulse: true, label: "Queued" },
  cancelled: { tone: "neutral", label: "Cancelled" },
  skipped: { tone: "neutral", label: "Skipped" },
};

export function StatusDot({ state, className }: { state: StatusState | string | null; className?: string }) {
  if (!state) return null;
  const style = STATUS_STYLES[state] ?? STATUS_STYLES.queued;
  return (
    <span
      title={style.label}
      className={cn(
        "inline-block size-2.5 shrink-0 rounded-full",
        TONE_FILL[style.tone],
        style.pulse && "animate-pulse-dot",
        className,
      )}
    >
      <span className="sr-only">{style.label}</span>
    </span>
  );
}

export function runState(status: string, conclusion: string | null): string {
  return status === "completed" ? (conclusion ?? "skipped") : status;
}