Toast

A transient notification that slides in from the bottom. Toasts confirm an action happened, surface a soft error, or nudge without interrupting. They auto-dismiss after 4s — never modal, never blocking. Max 2 lines, optional action.

Variants

Expense added ₹840 Swiggy order split with Priya and Rohan
All settled up 🎉 Goa trip is cleared. ₹4,200 settled with Aarav.
Payment failed UPI request to Kabir timed out. Try again.

Info (ink background) is the default — used for neutral confirmations like "expense added" or "group created." It doesn't require any action.

Success (teal background) is reserved for moments of resolution: a balance cleared, a group fully settled. Appears with confetti or celebratory language. Has an optional share action.

Error (coral background) surfaces a failure that the user should know about and may need to act on. Always includes a retry or dismiss action. Never use it for warnings — only actual failures.

Sizes

Single line
Two lines Second line of context — stays brief. Never more than two lines total.
PropertyValueNotes
Max width360pxCenters on wider viewports
Border radius14px (--r-md)Softer than a card, sharper than a pill
Padding13px 16pxComfortable without feeling bloated
Max lines2Title + 1 line of message. Clamp at 2 with ellipsis.
Z-index--z-toast (200)Above modals at 100, below tooltip at 300

States

Entering Slides up from bottom over 240ms
Resting Stays visible for 4 seconds, then exits
Exiting (opacity 0.4 preview) Slides back down over 240ms on dismiss
StateAnimationDuration
EntertranslateY(100%) → translateY(0) + opacity 0 → 1240ms --ease-out
RestingStatic4000ms (auto-dismiss timer)
Exit (auto)translateY(0) → translateY(100%) + opacity 1 → 0240ms --ease-out
Exit (action)Same as auto-exit — triggered immediately on action tap240ms --ease-out

On dark surfaces

Expense deleted Zomato ₹320 removed from Flat expenses
Priya paid you ₹640

Toast colors are self-contained — ink, teal, and coral all render correctly on dark backgrounds. No dark-mode variants needed. The toasts are opaque; the background behind them doesn't affect the text contrast.

Anatomy

Expense added ₹840 split with Priya, Rohan
Container (14px radius, shadow-float)
Icon (optional, 18px)
Body (title + message)
Action (optional)
PartElementNotes
Container.toast14px radius, shadow-float. Rendered in a portal at the bottom of the viewport.
Icon.toast-iconOptional. 18px SVG, 85% opacity for visual softness. Stroked, not filled.
Body.toast-bodyFlex column. Title (600 weight) + message (75% opacity, 2-line clamp).
Action.toast-actionOptional. Right-aligned. Semi-transparent background on the colored surface. Use for undo, retry, view — not dismiss.

Usage

Do Use toasts to confirm actions silently: "Expense added", "Group created", "Priya paid you". Auto-dismiss at 4s. Provide an undo action for destructive operations (delete expense, remove member).
Don't Don't show more than one toast at a time. Don't use toasts for errors that require immediate action — use a modal or inline error instead. Don't put more than 2 lines of text.
Do Success toasts for settlement moments are a celebration — use them warmly. "All settled up" not "Transaction complete". The action can be "Share" to let users celebrate with their group.
Don't Don't stack toasts. Don't interrupt ongoing gestures with a toast (wait for the interaction to complete). Don't use toasts as a persistent notification system — that's what the settle tab is for.

Accessibility

ARIA live region The toast portal container should have role="status" and aria-live="polite" for informational toasts. Error toasts use role="alert" and aria-live="assertive" — they interrupt the screen reader immediately.
Auto-dismiss The 4s timer must be paused when the toast has keyboard focus or when the pointer is hovering over it. Users must be able to read and interact before the toast disappears.
Reduced motion With prefers-reduced-motion: reduce, skip the slide animation. The toast appears and disappears instantly — no movement. The 4s auto-dismiss timer is unaffected.

Code

HTML structure

<!-- Portal container — one per page, lives at body root -->
<div class="toast-portal" role="status" aria-live="polite" aria-atomic="true"></div>

<!-- Info toast (inject into portal) -->
<div class="toast toast-info">
  <div class="toast-icon"><!-- SVG --></div>
  <div class="toast-body">
    <span class="toast-title">Expense added</span>
    <span class="toast-message">₹840 Swiggy split with Priya</span>
  </div>
</div>

<!-- Error toast with retry -->
<div class="toast toast-error" role="alert">
  <div class="toast-body">
    <span class="toast-title">Payment failed</span>
    <span class="toast-message">UPI timed out. Try again.</span>
  </div>
  <button class="toast-action">Retry</button>
</div>

JavaScript — show + auto-dismiss

function showToast({ variant = 'info', title, message, action, onAction, duration = 4000 }) {
  const portal = document.querySelector('.toast-portal');
  const toast = document.createElement('div');
  toast.className = `toast toast-${variant}`;
  toast.innerHTML = `
    <div class="toast-body">
      <span class="toast-title">${title}</span>
      ${message ? `<span class="toast-message">${message}</span>` : ''}
    </div>
    ${action ? `<button class="toast-action">${action}</button>` : ''}
  `;
  if (onAction) {
    toast.querySelector('.toast-action')?.addEventListener('click', () => { onAction(); dismiss(); });
  }
  portal.appendChild(toast);
  function dismiss() {
    toast.classList.add('toast-out');
    toast.addEventListener('animationend', () => toast.remove(), { once: true });
  }
  const timer = setTimeout(dismiss, duration);
  toast.addEventListener('mouseenter', () => clearTimeout(timer));
  toast.addEventListener('mouseleave', () => setTimeout(dismiss, duration));
  toast.addEventListener('focusin',    () => clearTimeout(timer));
  toast.addEventListener('focusout',   () => setTimeout(dismiss, duration));
}

Design tokens used

TokenValueRole
--ink#171513Info variant background
--teal#0E7C66Success variant background
--coral#E76F51Error variant background
--s-paper#FBF8F0Text on info + success toasts
--shadow-float0 30px 80px -30px rgba(23,21,19,.28)Toast elevation
--r-md14pxToast border radius
--d-med240msEnter/exit animation duration
--ease-outcubic-bezier(0.23,1,0.32,1)Slide easing
--z-toast200Stack order