Temporary message often containing an action.
<div class="snackbar" role="status" aria-live="polite">
<p class="snackbar__message">Conversation archived</p>
<button type="button" class="snackbar__action">Undo</button>
<span class="snackbar__timer" aria-hidden="true" style="animation-duration:5s;"></span>
</div>
<style>
.snackbar { position: relative; display: flex; align-items: center; gap: 16px; max-width: 380px; min-width: 260px;
padding: 12px 16px; box-sizing: border-box; border-radius: 10px; background: #241430; color: #FAF7F2;
font: 13.5px/1.4 system-ui, sans-serif; overflow: hidden; box-shadow: 0 10px 28px rgba(36,20,48,.25); }
.snackbar__message { flex: 1; margin: 0; }
.snackbar__action { border: none; background: transparent; color: #A8E6C1; font: 700 12.5px system-ui, sans-serif;
cursor: pointer; padding: 4px 6px; border-radius: 4px; white-space: nowrap; }
.snackbar__action:hover { background: #FAF7F218; }
.snackbar__action:focus-visible { outline: 2px solid #FAF7F2; outline-offset: 2px; }
.snackbar__timer { position: absolute; left: 0; bottom: 0; height: 3px; width: 100%; background: #A8E6C1;
transform-origin: left; }
@keyframes snackbar-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@media (prefers-reduced-motion: no-preference) {
.snackbar__timer { animation-name: snackbar-shrink; animation-timing-function: linear; animation-fill-mode: forwards; }
}
</style><div role="status" aria-live="polite" class="snackbar-tw relative flex items-center gap-4 max-w-sm min-w-[260px] px-4 py-3 box-border rounded-lg bg-[#241430] text-[#FAF7F2] font-sans text-[13.5px] overflow-hidden shadow-lg">
<p class="flex-1 m-0">Conversation archived</p>
<button type="button" class="border-0 bg-transparent text-[#A8E6C1] font-bold text-[12.5px] cursor-pointer px-1.5 py-1 rounded whitespace-nowrap hover:bg-white/10">Undo</button>
<span aria-hidden="true" class="snackbar-tw__timer absolute left-0 bottom-0 h-[3px] w-full bg-[#A8E6C1] origin-left" style="animation-duration:5s;"></span>
</div>
<style>
@keyframes snackbar-tw-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@media (prefers-reduced-motion: no-preference) {
.snackbar-tw__timer { animation-name: snackbar-tw-shrink; animation-timing-function: linear; animation-fill-mode: forwards; }
}
</style>export function Snackbar({
message = "Conversation archived",
actionLabel = "Undo",
showAction = true,
duration = 5,
}) {
return (
<div role="status" aria-live="polite" style={{ position: "relative", display: "flex", alignItems: "center", gap: 16,
maxWidth: 380, minWidth: 260, padding: "12px 16px", boxSizing: "border-box", borderRadius: 10, background: "#241430",
color: "#FAF7F2", font: "13.5px/1.4 system-ui, sans-serif", overflow: "hidden", boxShadow: "0 10px 28px rgba(36,20,48,.25)" }}>
<p style={{ flex: 1, margin: 0 }}>{message}</p>
{showAction && (
<button type="button" style={{ border: "none", background: "transparent", color: "#A8E6C1", fontWeight: 700,
fontSize: 12.5, cursor: "pointer", padding: "4px 6px", borderRadius: 4, whiteSpace: "nowrap" }}>{actionLabel}</button>
)}
<span aria-hidden="true" className="snackbar-timer" style={{ position: "absolute", left: 0, bottom: 0, height: 3, width: "100%", background: "#A8E6C1",
transformOrigin: "left" }} />
<style>{`
@media (prefers-reduced-motion: no-preference) {
.snackbar-timer { animation: snackbar-react-shrink ${duration}s linear forwards; }
@keyframes snackbar-react-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }
}
`}</style>
</div>
);
}