Skip to main content
Pricing

Toast

Free

A brief, non-modal notification that appears temporarily at the edge of the viewport to confirm an action or report a status change. Toasts auto-dismiss after 5 seconds by default, stack vertically when multiple appear, and include an optional dismiss button. Supports info, success, warning, and error severity levels. Error toasts must not auto-dismiss — they persist until the user explicitly closes them.

12 variants

Variant
Info notification received.

Variants

VariantDescriptionWhen to use
InfoBlue-toned toast for neutral status updates.Use for non-critical confirmations — "Link copied to clipboard", "Settings updated".
SuccessGreen-toned toast confirming a completed action.Use after successful operations — "File uploaded", "Invitation sent".
WarningAmber-toned toast for conditions that may need attention.Use for non-blocking warnings — "You are approaching your usage limit".
ErrorRed-toned toast for action failures. Does not auto-dismiss.Use when an action fails — "Failed to save changes", "Network error".

Usage Guidelines

Do

Auto-dismiss info, success, and warning toasts after 5 seconds.

Don't

Use toasts for critical errors that require immediate user action — use Alert or a dialog.

Do

Never auto-dismiss error toasts — they must persist until closed by the user.

Don't

Display more than 3 toasts simultaneously — queue excess toasts.

Do

Use aria-live="polite" so screen readers announce the toast without interrupting.

Don't

Use toasts for information the user needs to reference later — it will disappear.

Do

Stack multiple toasts vertically with the newest at the bottom.

Don't

Code

HTML
<div class="lex-toast-container" aria-live="polite" aria-atomic="true">
  <div class="lex-toast lex-toast--success" role="status">
    <svg class="lex-toast__icon" aria-hidden="true"><!-- check icon --></svg>
    <p class="lex-toast__message">File uploaded successfully.</p>
    <button class="lex-toast__close" aria-label="Dismiss notification">
      <svg aria-hidden="true"><!-- close icon --></svg>
    </button>
  </div>
</div>

<div class="lex-toast lex-toast--error" role="alert">
  <svg class="lex-toast__icon" aria-hidden="true"><!-- error icon --></svg>
  <p class="lex-toast__message">Failed to save changes.</p>
  <button class="lex-toast__action">Retry</button>
  <button class="lex-toast__close" aria-label="Dismiss notification">
    <svg aria-hidden="true"><!-- close icon --></svg>
  </button>
</div>
CSS Custom Properties
.lex-toast-container {
  position: fixed;
  bottom: var(--lex-space-24);
  right: var(--lex-space-24);
  display: flex;
  flex-direction: column;
  gap: var(--lex-space-8);
  z-index: var(--lex-z-toast, 9000);
  pointer-events: none;
}

.lex-toast {
  display: flex;
  align-items: center;
  gap: var(--lex-space-8);
  padding: var(--lex-space-12) var(--lex-space-16);
  border-radius: var(--lex-radius-lg);
  background: var(--lex-bg-surface-raised);
  border: 1px solid var(--lex-toast-border);
  box-shadow: var(--lex-shadow-lg);
  pointer-events: auto;
  animation: lex-toast-in 200ms ease-out;
}

.lex-toast--success { --lex-toast-border: var(--lex-border-success); }
.lex-toast--error   { --lex-toast-border: var(--lex-border-danger); }
.lex-toast--warning { --lex-toast-border: var(--lex-border-warning); }
.lex-toast--info    { --lex-toast-border: var(--lex-border-info); }

.lex-toast__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
}

.lex-toast__message {
  font-size: var(--lex-font-size-sm);
  margin: 0;
  flex: 1;
}

.lex-toast__action {
  font-size: var(--lex-font-size-sm);
  font-weight: 600;
  color: var(--lex-text-brand);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  white-space: nowrap;
}

.lex-toast__close {
  flex-shrink: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--lex-text-muted);
}

@keyframes lex-toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
React
// Using Lexicon CSS classes with React

export function UploadHandler() {
  const handleUpload = async (file: File) => {
    try {
      await uploadFile(file);
      toast.success('File uploaded successfully.');
    } catch (err) {
      toast.error('Failed to upload file.', {
        action: { label: 'Retry', onClick: () => handleUpload(file) },
      });
    }
  };

  return <UploadArea onUpload={handleUpload} />;
}

// Toast with undo action
function DeleteItem({ id }: { id: string }) {
  const handleDelete = async () => {
    await deleteItem(id);
    toast.success('Item deleted.', {
      action: { label: 'Undo', onClick: () => restoreItem(id) },
    });
  };

  return <Button variant="danger" onClick={handleDelete}>Delete</Button>;
}

Design Tokens

TokenValue (dark)Value (light)CSS property
--lex-toast-bgbg
--lex-toast-borderborder
--lex-toast-radiusradius
--lex-toast-shadowshadow
--lex-toast-paddingpadding

Accessibility

  • Toast container uses aria-live="polite" so announcements do not interrupt the user.
  • Error toasts should use role="alert" for a more assertive announcement.
  • Never auto-dismiss error toasts — they must persist until manually closed.
  • Dismiss button requires aria-label="Dismiss notification".
  • Action buttons inside toasts must be keyboard-accessible.
  • Pause the auto-dismiss timer when the user hovers over or focuses within the toast.

Keyboard Interactions

TabMoves focus to the action button or dismiss button within the toast.
Enter/SpaceActivates the focused action or dismiss button.
EscapeDismisses the most recent toast.