iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Toasts / Alerts

Ionic toasts: ion-toast for transient feedback. Positioning, duration, buttons, and accessibility.

Ionic — toasts

EXAMPLE
# ===== Programmatic toast (Angular) =====
import { ToastController } from '@ionic/angular';

constructor(private toast: ToastController) {}

async showSaved() {
  const t = await this.toast.create({
    message: 'Saved.',
    duration: 1500,
    position: 'top',           // 'top' | 'middle' | 'bottom'
    color: 'success',           // success | warning | danger | medium | dark
  });
  await t.present();
}

# ===== With buttons (e.g. undo) =====
async showDeleted(undo: () => void) {
  const t = await this.toast.create({
    message: 'Item deleted.',
    duration: 3000,
    color: 'medium',
    buttons: [
      { text: 'Undo', role: 'cancel', handler: undo },
      { icon: 'close', role: 'cancel' },
    ],
  });
  await t.present();
}

# ===== React =====
import { useIonToast } from '@ionic/react';
const [present] = useIonToast();
present({ message: 'Saved.', duration: 1500, position: 'top' });

# ===== Vue =====
import { toastController } from '@ionic/vue';
const t = await toastController.create({ message: 'Saved.', duration: 1500 });
await t.present();

# ===== Template / declarative form =====
<ion-toast
  [isOpen]="isToastOpen"
  message="Saved."
  duration="1500"
  (didDismiss)="isToastOpen = false"
></ion-toast>

# ===== Stacking + queueing =====
# Multiple toasts queue automatically; the next one appears after the current dismisses.
# Avoid spamming the user — debounce or coalesce in your service.

# ===== Accessibility =====
# - Ion-toast announces the message to screen readers
# - For longer / important messages, use ion-alert instead (focus + interactive)
# - Avoid using toasts as primary CTAs; they disappear

# ===== Positioning + anchor =====
# 'top' near the status bar; 'bottom' near the tab bar.
# Avoid 'middle' for short messages; users may miss it.
# On iOS, toasts respect safe-area insets automatically.

# ===== Custom colours / CSS =====
ion-toast::part(message) { font-weight: 600; }
ion-toast.custom { --background: #2a2a3a; --color: #fff; }

# ===== Common bugs =====
# - Forgetting 'await t.present()' (toast never appears)
# - Memory leak from leaving subscriptions inside handler (use auto-cancel patterns)
# - Toasts for errors that should be ion-alert (transient error swallowed)
# - Long messages > 2-3 lines (truncated; use alerts)

# ===== Patterns to internalise =====
# - Top position on phones (closer to thumb? bottom; reachable? top)
# - 1500-3000ms duration; pair with an Undo button for destructive actions
# - One toast service in the app; never inline ToastController.create in every component
# - Accessibility: pair with screen-reader-friendly alert for important messages

# ===== Pitfalls =====
# - Toasts as the ONLY feedback for destructive actions (use confirm + toast)
# - Same toast queued multiple times -> noise
# - Async handler errors not caught (the toast dismisses but the action fails silently)
# - Inconsistent colours across the app — wrap in a UI toast service

Why it matters

Toasts are transient feedback. Use ion-toast with duration + position + colour for confirmations and undo flows; reach for ion-alert when interaction is required. Wrap in a single toast service so the team uses consistent shapes; never let a toast be the only feedback for a destructive action.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
const toast = await this.toastCtrl.create({
    message: 'Saved',
    duration: 1500,
    color: 'success',
});
await toast.present();
Try it Yourself »

Discussion

Loading…