The Kit/Components

Status Pip

Lifecycle state chip for processes and services: a solid square pip + mono uppercase label, coloured by theme tokens. Only the starting state animates, as a hard-step blink with no glow; reduced motion disables it.

loading…
StatusPip.tsx
import * as React from "react";

export type PipState = "idle" | "starting" | "running" | "degraded" | "stopped" | "error";

export interface StatusPipProps {
  state: PipState;
  /** Text beside the pip; defaults to the state name. */
  label?: string;
  /** Pip square size in px. */
  size?: number;
  className?: string;
  style?: React.CSSProperties;
}

const STATE_COLOR: Record<PipState, string> = {
  idle: "var(--ink-faint, #8a8f98)",
  starting: "var(--accent, #c2f53b)",
  running: "var(--good, #3ecf6e)",
  degraded: "var(--warn, #e8b13c)",
  stopped: "var(--ink-dim, #a7abb4)",
  error: "var(--bad, #ff2e43)",
};

/**
 * Lifecycle state chip for processes, services, runnables: a solid square pip
 * plus a mono uppercase label. Colour comes from theme tokens (--good / --warn /
 * --bad / --accent / --ink-*), so it follows whatever theme surface it sits on.
 * Only `starting` animates, and it blinks in hard steps (no fade, no glow);
 * the blink is disabled under prefers-reduced-motion.
 */
export function StatusPip({ state, label, size = 8, className, style }: StatusPipProps) {
  const blinking = state === "starting";
  return (
    <span className={className} style={{ display: "inline-flex", alignItems: "center", gap: 7, ...style }}>
      <style>{`@keyframes kit-pip-blink{0%,49%{opacity:1}50%,100%{opacity:.25}}@media (prefers-reduced-motion:reduce){.kit-pip-blink{animation:none!important}}`}</style>
      <span
        aria-hidden
        className={blinking ? "kit-pip-blink" : undefined}
        style={{
          width: size,
          height: size,
          borderRadius: 1,
          background: STATE_COLOR[state],
          flex: "0 0 auto",
          animation: blinking ? "kit-pip-blink 1.1s linear infinite" : undefined,
        }}
      />
      <span
        style={{
          fontFamily: "var(--font-mono, monospace)",
          fontSize: 10,
          letterSpacing: 1.2,
          textTransform: "uppercase",
          color: "var(--ink-dim, #a7abb4)",
        }}
      >
        {label ?? state}
      </span>
    </span>
  );
}
← The whole kit