Workflow-App/Workflow/components/StatusBadge.tsx

61 lines
2.6 KiB
TypeScript
Raw Permalink Normal View History

// components/StatusBadge.tsx
// Tiny pill used to communicate derived company / director status.
// Three semantic colors: green for active, red for deregistered,
// amber for in-process / inactive. Empty states get a neutral
// Hairline Gray pill so the row never shifts when data is missing.
type Variant =
| "success"
| "danger"
| "warn"
| "muted"
| "active"
| "inactive"
| "in_process"
| "deregistered"
| "client";
// Mix against var(--surface) (not white) so badges blend into whatever
// surface the page is sitting on. In light mode surface ≈ white so the
// wash stays the same; in dark mode the wash becomes a subtle dark tint
// instead of a bright washed-out rectangle. 18% (vs 14%) lifts the
// chroma enough that the colour reads at the same perceptual weight in
// both themes.
const VARIANT_STYLES: Record<Variant, string> = {
success: "bg-[color-mix(in_oklch,var(--success)_18%,var(--surface))] text-[color:var(--success)] border-[color:var(--success)]/55",
danger: "bg-[color-mix(in_oklch,var(--danger)_18%,var(--surface))] text-[color:var(--danger)] border-[color:var(--danger)]/55",
warn: "bg-[color-mix(in_oklch,var(--warn)_18%,var(--surface))] text-[color:var(--warn)] border-[color:var(--warn)]/55",
muted: "bg-surface-warm text-muted border-border",
active: "bg-[color-mix(in_oklch,var(--success)_18%,var(--surface))] text-[color:var(--success)] border-[color:var(--success)]/55",
inactive: "bg-[color-mix(in_oklch,var(--meta)_18%,var(--surface))] text-muted border-border",
in_process: "bg-[color-mix(in_oklch,var(--warn)_18%,var(--surface))] text-[color:var(--warn)] border-[color:var(--warn)]/55",
deregistered: "bg-[color-mix(in_oklch,var(--danger)_18%,var(--surface))] text-[color:var(--danger)] border-[color:var(--danger)]/55",
// Brand coral, populated from --accent. The active "you are the
// accountant for this entity" ribbon.
client: "bg-[color-mix(in_oklch,var(--accent)_18%,var(--surface))] text-[color:var(--accent)] border-[color:var(--accent)]/55"
};
interface StatusBadgeProps {
variant: Variant;
children: React.ReactNode;
}
export default function StatusBadge({ variant, children }: StatusBadgeProps) {
return (
<span
data-od-id="status-badge"
className={
"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-pill border text-xs font-semibold whitespace-nowrap " +
VARIANT_STYLES[variant]
}
>
<span
aria-hidden="true"
className="w-1.5 h-1.5 rounded-pill"
style={{ backgroundColor: "currentColor" }}
/>
{children}
</span>
);
}