material-snackbar

MD3 transient message at the bottom of the UI. material-snackbar-host owns positioning + queue; one visible at a time per spec.

Single line — auto-dismiss after 5 s

Default behavior. Per MD3 a11y, prefer also surfacing the same information inline near the action that triggered the snackbar.

With action — stays until acted on

Action-bearing snackbars do not auto-dismiss. Click Undo or wait — it will not vanish on its own.

Two-line message

Long supporting text wraps to a second line on compact widths.

Closable + sticky

duration="0" + closable. Useful for important messages that must be acknowledged.

Queue burst — four messages at once

MD3 forbids stacking. The host shows the first message, waits for it to dismiss (timeout, action, or close), then shows the next.

Replace by id — progressive feedback

Re-enqueueing with the same id updates the visible snackbar in place instead of waiting in line.

Django messages simulation

Treats a payload like django.contrib.messages output. error/warning become sticky + closable; the rest auto-dismiss.

Last close reason

(none)
Sample usage
<!-- Place once near the body root, or use ensureSnackbarHost() to auto-create -->
<material-snackbar-host placement="bottom"></material-snackbar-host>

<script>
  const host = document.querySelector('material-snackbar-host');

  host.enqueue({ message: 'Saved.' });                         // transient
  host.enqueue({ message: 'Archived.', actionLabel: 'Undo',
                 onAction: () => restore() });                 // sticky w/ action
  host.enqueue({ message: 'Save failed.', closable: true,
                 duration: 0, assertive: true });              // sticky error

  // Replace in place
  host.enqueue({ id: 'save', message: 'Saving…', duration: 0 });
  setTimeout(() => host.enqueue({ id: 'save', message: 'Saved.' }), 800);

  // Map django.contrib.messages → snackbars
  for (const m of django_messages) {
    host.enqueue({
      message: m.text,
      closable: m.level === 'error' || m.level === 'warning',
      duration: (m.level === 'error' || m.level === 'warning') ? 0 : 5000,
      assertive: m.level === 'error',
    });
  }
</script>