kcolbchain  /  brand  /  components

toasts

A toast is a short-lived status event: one line of outcome, one line of context, then it gets out of the way. Use it after a local action succeeds, needs attention, or fails.

variants

<div class="toast-region" aria-live="polite" aria-label="Notifications"></div>

<button data-toast="success">success</button>
<button data-toast="warning">warning</button>
<button data-toast="error">error</button>

markup

<div class="toast success" role="status">
  <div class="bar"></div>
  <div>
    <div class="title">payment indexed</div>
    <div class="body">settlement proof accepted on Base</div>
  </div>
  <button class="close" type="button" aria-label="Dismiss notification">×</button>
</div>

css

.toast-region {
  position: fixed; right: var(--s-4); bottom: var(--s-4); z-index: 20;
  display: grid; gap: var(--s-2);
  width: min(360px, calc(100vw - (var(--s-4) * 2)));
  pointer-events: none;
}
.toast {
  display: grid; grid-template-columns: 4px 1fr auto; gap: var(--s-3);
  padding: var(--s-3); border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-elev); color: var(--fg);
  pointer-events: auto; animation: toast-in .18s ease-out both;
}
.toast.is-leaving { animation: toast-out .22s ease-in forwards; }
.toast.success .bar { background: var(--ok); }
.toast.warning .bar { background: var(--warn); }
.toast.error .bar { background: var(--hot); }
.toast.success { border-color: var(--ok-soft); }
.toast.warning { border-color: var(--warn-soft); }
.toast.error { border-color: var(--hot-soft); }

javascript

const toasts = document.querySelector('.toast-region');
const messages = {
  success: ['payment indexed', 'settlement proof accepted on Base'],
  warning: ['gas drifting', 'retry window increased to 30 seconds'],
  error: ['oracle rejected', 'signature mismatch on payload hash'],
};

function dismiss(toast) {
  toast.classList.add('is-leaving');
  toast.addEventListener('animationend', () => toast.remove(), { once: true });
}

function pushToast(variant) {
  const [title, body] = messages[variant];
  const toast = document.createElement('div');
  toast.className = `toast ${variant}`;
  toast.setAttribute('role', variant === 'error' ? 'alert' : 'status');
  toast.innerHTML = `<div class="bar"></div>
    <div><div class="title">${title}</div><div class="body">${body}</div></div>
    <button class="close" type="button" aria-label="Dismiss notification">×</button>`;
  toast.querySelector('.close').addEventListener('click', () => dismiss(toast));
  toasts.append(toast);
  window.setTimeout(() => dismiss(toast), 5000);
}