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…