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.
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>
);
}