Alert

Important message requiring attention.

html

<div class="alert alert--warning" role="alert" aria-live="assertive">
  <span class="alert__icon" aria-hidden="true"></span>
  <div class="alert__body">
    <p class="alert__title">Update required</p>
    <p class="alert__message">Your session expires in 5 minutes. Save your work to avoid losing changes.</p>
  </div>
  <button type="button" class="alert__close" aria-label="Dismiss Update required">×</button>
</div>
<style>
.alert { display: flex; align-items: flex-start; gap: 12px; max-width: 420px; padding: 14px 16px;
  border-radius: 10px; border: 1px solid; box-sizing: border-box; font: 14px/1.45 system-ui, sans-serif; background: #FAF7F2; }
.alert__icon { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; margin-top: 1px; position: relative; }
.alert__icon::before { position: absolute; inset: 0; display: grid; place-items: center; font: 700 12px/1 system-ui, sans-serif; color: #FAF7F2; }
.alert--info { border-color: #2F6FA8; background: color-mix(in srgb, #2F6FA8 8%, #FAF7F2); }
.alert--info .alert__icon { background: #2F6FA8; }
.alert--info .alert__icon::before { content: "i"; }
.alert--success { border-color: #2F8F5B; background: color-mix(in srgb, #2F8F5B 8%, #FAF7F2); }
.alert--success .alert__icon { background: #2F8F5B; }
.alert--success .alert__icon::before { content: "✓"; }
.alert--warning { border-color: #B4790A; background: color-mix(in srgb, #B4790A 8%, #FAF7F2); }
.alert--warning .alert__icon { background: #B4790A; }
.alert--warning .alert__icon::before { content: "!"; }
.alert--error { border-color: #B3261E; background: color-mix(in srgb, #B3261E 8%, #FAF7F2); }
.alert--error .alert__icon { background: #B3261E; }
.alert--error .alert__icon::before { content: "×"; }
.alert__body { flex: 1; }
.alert__title { margin: 0 0 2px; font-weight: 700; color: #241430; }
.alert__message { margin: 0; color: #241430cc; }
.alert__close { border: none; background: transparent; font-size: 16px; line-height: 1; cursor: pointer; color: #241430; padding: 2px; border-radius: 4px; }
.alert__close:hover { background: #24143014; }
.alert__close:focus-visible { outline: 2px solid #241430; outline-offset: 2px; }
</style>

tailwind

<div role="alert" aria-live="assertive" class="alert-tw alert-tw--warning flex items-start gap-3 max-w-md p-3.5 rounded-lg border box-border bg-[#FAF7F2] font-sans text-sm">
  <span class="alert-tw__icon w-[22px] h-[22px] rounded-full flex-shrink-0 mt-px" aria-hidden="true"></span>
  <div class="flex-1">
    <p class="m-0 mb-0.5 font-bold text-[#241430]">Update required</p>
    <p class="m-0 text-[#241430]/80">Your session expires in 5 minutes. Save your work to avoid losing changes.</p>
  </div>
  <button type="button" aria-label="Dismiss Update required" class="border-0 bg-transparent text-base leading-none cursor-pointer p-0.5 rounded text-[#241430] hover:bg-black/5">×</button>
</div>
<style>
.alert-tw__icon { position: relative; }
.alert-tw__icon::before { position: absolute; inset: 0; display: grid; place-items: center; font: 700 12px/1 system-ui, sans-serif; color: #FAF7F2; }
.alert-tw--info { border-color: #2F6FA8; background: color-mix(in srgb, #2F6FA8 8%, #FAF7F2); }
.alert-tw--info .alert-tw__icon { background: #2F6FA8; }
.alert-tw--info .alert-tw__icon::before { content: "i"; }
.alert-tw--success { border-color: #2F8F5B; background: color-mix(in srgb, #2F8F5B 8%, #FAF7F2); }
.alert-tw--success .alert-tw__icon { background: #2F8F5B; }
.alert-tw--success .alert-tw__icon::before { content: "✓"; }
.alert-tw--warning { border-color: #B4790A; background: color-mix(in srgb, #B4790A 8%, #FAF7F2); }
.alert-tw--warning .alert-tw__icon { background: #B4790A; }
.alert-tw--warning .alert-tw__icon::before { content: "!"; }
.alert-tw--error { border-color: #B3261E; background: color-mix(in srgb, #B3261E 8%, #FAF7F2); }
.alert-tw--error .alert-tw__icon { background: #B3261E; }
.alert-tw--error .alert-tw__icon::before { content: "×"; }
</style>

react

export function Alert({
  title = "Update required",
  message = "Your session expires in 5 minutes. Save your work to avoid losing changes.",
  severity = "warning",
  dismissible = true,
}) {
  const palette = {
    info: { c: "#2F6FA8", icon: "i" },
    success: { c: "#2F8F5B", icon: "✓" },
    warning: { c: "#B4790A", icon: "!" },
    error: { c: "#B3261E", icon: "×" },
  }[severity] ?? { c: "#2F6FA8", icon: "i" };
  return (
    <div role="alert" aria-live="assertive" style={{ display: "flex", alignItems: "flex-start", gap: 12, maxWidth: 420,
      padding: "14px 16px", borderRadius: 10, border: `1px solid ${palette.c}`, boxSizing: "border-box",
      font: "14px/1.45 system-ui, sans-serif", background: `color-mix(in srgb, ${palette.c} 8%, #FAF7F2)` }}>
      <span aria-hidden="true" style={{ width: 22, height: 22, borderRadius: "50%", flexShrink: 0, marginTop: 1,
        background: palette.c, display: "grid", placeItems: "center", color: "#FAF7F2", fontSize: 12, fontWeight: 700 }}>{palette.icon}</span>
      <div style={{ flex: 1 }}>
        <p style={{ margin: "0 0 2px", fontWeight: 700, color: "#241430" }}>{title}</p>
        <p style={{ margin: 0, color: "#241430cc" }}>{message}</p>
      </div>
      {dismissible && (
        <button type="button" aria-label={`Dismiss ${title}`} style={{ border: "none", background: "transparent",
          fontSize: 16, cursor: "pointer", color: "#241430", padding: 2, borderRadius: 4 }}>×</button>
      )}
    </div>
  );
}