Files
ersatztv/design-system/components/feedback/Toast.jsx
T
2026-07-02 07:37:00 +02:00

47 lines
2.3 KiB
React

import React from "react";
const map = {
ok: { c: "var(--status-ok)", bg: "var(--ctv-ok-soft)", icon: "M5 12.5l4.5 4.5L19 7" },
warn: { c: "var(--status-warn)", bg: "var(--ctv-warn-soft)", icon: "M12 8v5M12 17h.01" },
error: { c: "var(--status-error)", bg: "var(--ctv-error-soft)", icon: "M12 8v5M12 17h.01" },
info: { c: "var(--ctv-accent)", bg: "var(--ctv-accent-soft)", icon: "M12 11v5M12 8h.01" },
};
/**
* Toast / inline alert. Icon, message, optional close.
*/
export function Toast({ tone = "info", title, message, onClose, style = {} }) {
const t = map[tone] || map.info;
return (
<div
role="status"
style={{
display: "flex",
alignItems: "flex-start",
gap: "11px",
width: "min(380px, 100%)",
padding: "12px 13px",
background: "var(--surface-raised)",
border: "1px solid var(--border-hairline)",
borderLeft: `2px solid ${t.c}`,
borderRadius: "var(--radius-md)",
boxShadow: "var(--shadow-md)",
...style,
}}
>
<span style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", width: 22, height: 22, borderRadius: "var(--radius-xs)", background: t.bg, flex: "0 0 auto", marginTop: 1 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke={t.c} strokeWidth="0" fill="none" /><path d={t.icon} stroke={t.c} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" /></svg>
</span>
<div style={{ flex: 1, minWidth: 0 }}>
{title && <div style={{ font: "var(--weight-semibold) var(--text-sm)/1.3 var(--font-sans)", color: "var(--text-primary)" }}>{title}</div>}
{message && <div style={{ marginTop: title ? 2 : 0, font: "var(--text-xs)/1.45 var(--font-sans)", color: "var(--text-secondary)" }}>{message}</div>}
</div>
{onClose && (
<button type="button" onClick={onClose} aria-label="Dismiss" style={{ display: "inline-flex", padding: 3, border: "none", background: "transparent", color: "var(--text-disabled)", cursor: "pointer", flex: "0 0 auto" }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" /></svg>
</button>
)}
</div>
);
}