Badge
A tinted, square-cornered plate carrying a state word. Three vocabularies:
<Badge status="success" dot>Supported</Badge> // outcome: did it succeed
<Badge state="running">Running</Badge> // workflow: where work has got to
<Badge state="needs_review">Needs review</Badge>
<Badge decision="denied">Denied</Badge> // approval decisionsstatus: neutral · success · warning · danger · info — optional dot.
state: queued · running · needs-input · needs-review · done · failed (snake_case accepted).
decision: pending · approved · denied · expired.
State/decision badges are hairline-bordered and always marked: queued and expired render a hollow ring (nothing is asked of anyone / nobody decided), the rest a filled dot. Queued and done share stone deliberately — the mark tells them apart. Colour is never the sole carrier.
Preview
Declarations
export type WorkflowState = 'queued' | 'running' | 'needs-input' | 'needs-review' | 'done' | 'failed';
export type Decision = 'pending' | 'approved' | 'denied' | 'expired';
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
/** Outcome semantics — did the thing succeed or fail. */
status?: 'neutral' | 'success' | 'warning' | 'danger' | 'info';
/** Workflow state — where a piece of work has got to. Overrides `status`.
* Always rendered with a mark: hollow ring for queued, filled dot
* otherwise (colour is never the sole carrier). Accepts snake_case too. */
state?: WorkflowState;
/** Approval decision. `expired` takes the hollow ring — nobody decided. */
decision?: Decision;
/** Show a leading dot (status badges only; state/decision always show one). */
dot?: boolean;
className?: string;
children?: React.ReactNode;
}
/**
* A tinted status plate carrying a state word — SUPPORTED, RUNNING,
* NEEDS REVIEW, DENIED. Square corners; reads like an engraved indicator.
*/
export function Badge(props: BadgeProps): React.JSX.Element;