Files
ersatztv/design-system/components/data-display/StatusDot.jsx
T
2026-07-02 07:37:00 +02:00

38 lines
1.3 KiB
React

import React from "react";
const colors = {
live: "var(--status-live)",
ok: "var(--status-ok)",
warn: "var(--status-warn)",
error: "var(--status-error)",
idle: "var(--text-disabled)",
};
/**
* Status dot with optional pulsing ring — on-air / live indicators.
*/
export function StatusDot({ status = "idle", pulse = false, size = 8, label, style = {} }) {
const c = colors[status] || colors.idle;
const doPulse = pulse || status === "live";
return (
<span style={{ display: "inline-flex", alignItems: "center", gap: "7px", ...style }}>
<span style={{ position: "relative", width: size, height: size, flex: "0 0 auto" }}>
{doPulse && (
<span
style={{
position: "absolute",
inset: 0,
borderRadius: "50%",
background: c,
animation: "ctv-ping 1.6s cubic-bezier(0,0,0.2,1) infinite",
}}
/>
)}
<span style={{ position: "absolute", inset: 0, borderRadius: "50%", background: c, boxShadow: doPulse ? `0 0 6px ${c}` : "none" }} />
<style>{`@keyframes ctv-ping{0%{transform:scale(1);opacity:.55}70%,100%{transform:scale(2.4);opacity:0}}`}</style>
</span>
{label && <span style={{ font: "var(--text-xs)/1 var(--font-sans)", color: "var(--text-secondary)" }}>{label}</span>}
</span>
);
}