NETFRAME_DOCS // TOAST
GITHUB

Toast

Non-blocking notifications stacked in a fixed region. The left border accent communicates message type.

Variants

SUCCESS / ERROR / WARNING / INFO

UPLINK_RESTORED
Connection re-established. Latency: 12ms.
CONNECTION_LOST
Node 047 unreachable. Retrying in 5s.
HIGH_LATENCY
Uplink degraded. Current latency: 420ms.
SYNC_COMPLETE
48 records synchronized with remote node.
<div class="nf-toast nf-toast-success">
<div class="nf-toast-content">
  <div class="nf-toast-title">UPLINK_RESTORED</div>
  <div class="nf-toast-message">Connection re-established. Latency: 12ms.</div>
</div>
<button class="nf-toast-close" aria-label="Dismiss">✕</button>
</div>

<div class="nf-toast nf-toast-error">
<div class="nf-toast-content">
  <div class="nf-toast-title">CONNECTION_LOST</div>
  <div class="nf-toast-message">Node 047 unreachable. Retrying in 5s.</div>
</div>
<button class="nf-toast-close" aria-label="Dismiss">✕</button>
</div>

<div class="nf-toast nf-toast-warning">
<div class="nf-toast-content">
  <div class="nf-toast-title">HIGH_LATENCY</div>
  <div class="nf-toast-message">Uplink degraded. Current latency: 420ms.</div>
</div>
<button class="nf-toast-close" aria-label="Dismiss">✕</button>
</div>

<div class="nf-toast nf-toast-info">
<div class="nf-toast-content">
  <div class="nf-toast-title">SYNC_COMPLETE</div>
  <div class="nf-toast-message">48 records synchronized with remote node.</div>
</div>
<button class="nf-toast-close" aria-label="Dismiss">✕</button>
</div>

Usage

Append toasts into a fixed .nf-toast-region live region (present in the page before the first toast, so screen readers pick up insertions), then remove them after a timeout:

<div class="nf-toast-region nf-toast-top-right" id="toast-region" aria-live="polite"></div>
function showToast({ title, message, type = 'info', duration = 4000 }) {
  const region = document.getElementById('toast-region');
  const toast = document.createElement('div');
  toast.className = `nf-toast nf-toast-${type}`;
  // Errors interrupt; everything else waits for the polite region.
  if (type === 'error') toast.setAttribute('role', 'alert');

  // Build with textContent, never innerHTML: titles and messages often
  // contain user or server data.
  const content = document.createElement('div');
  content.className = 'nf-toast-content';
  const heading = document.createElement('div');
  heading.className = 'nf-toast-title';
  heading.textContent = title;
  const body = document.createElement('div');
  body.className = 'nf-toast-message';
  body.textContent = message;
  content.append(heading, body);

  const close = document.createElement('button');
  close.type = 'button';
  close.className = 'nf-toast-close';
  close.setAttribute('aria-label', 'Dismiss');
  close.textContent = '✕';
  toast.append(content, close);

  let timer;
  let removed = false;
  const remove = () => {
    if (removed) return;
    removed = true;
    toast.remove();
  };
  const dismiss = () => {
    clearTimeout(timer);
    toast.classList.add('nf-toast-dismissing');
    toast.addEventListener('animationend', remove, { once: true });
    setTimeout(remove, 1000); // fallback if animations are disabled
  };
  const start = () => { clearTimeout(timer); timer = setTimeout(dismiss, duration); };
  const pause = () => clearTimeout(timer);

  // Let people stop the timer while reading or interacting (WCAG 2.2.1).
  toast.addEventListener('mouseenter', pause);
  toast.addEventListener('mouseleave', start);
  toast.addEventListener('focusin', pause);
  toast.addEventListener('focusout', start);
  close.addEventListener('click', dismiss);

  region.appendChild(toast);
  start();
  return toast;
}

Region positions

Class Position
nf-toast-top-right Top-right (default)
nf-toast-top-left Top-left
nf-toast-bottom-right Bottom-right
nf-toast-bottom-left Bottom-left

Class reference

Class Description
nf-toast-region Fixed container — stacks toasts vertically
nf-toast Individual notification
nf-toast-success Primary green left border
nf-toast-error Error red left border
nf-toast-warning Secondary magenta left border
nf-toast-info Tertiary purple left border
nf-toast-dismissing Triggers the slide-out exit animation
nf-toast-content Flex column wrapper for title + message
nf-toast-title Label-font heading
nf-toast-message Body text
nf-toast-close Dismiss button