Toast Notifications
The application uses HeroUI's native Toast component for user feedback and notifications.
Overview
Toast notifications provide temporary, non-blocking feedback for user actions like:
- Successful mutations (create, update, delete)
- Error messages
- Loading states
- Informational messages
Setup
The toast system is configured in apps/web/src/main.tsx:
import { ToastProvider } from '@heroui/toast';
<ToastProvider
placement="top-right"
maxVisibleToasts={3}
toastProps={{
timeout: 4000,
hideCloseButton: false,
}}
/>;
Basic Usage
Simple Toasts
import { useToast } from '@/hooks/useToast';
function MyComponent() {
const toast = useToast();
const handleSuccess = () => {
toast.success('Guild created successfully!');
};
const handleError = () => {
toast.error('Failed to save changes', 'Please try again');
};
const handleInfo = () => {
toast.info('Processing your request...');
};
const handleWarning = () => {
toast.warning('Low disk space', 'Consider cleaning up');
};
}
RTK Query Integration
Promise-Based Toasts
For RTK Query mutations, use useToastMutations for automatic loading/success/error states:
import { useToastMutations } from '@/hooks/useToastMutations';
import { useCreateGuildMutation } from '@/store/api/guildsApi';
function CreateGuildForm() {
const [createGuild] = useCreateGuildMutation();
const { toastPromise } = useToastMutations();
const handleSubmit = async (data: GuildFormData) => {
await toastPromise(createGuild(data).unwrap(), {
loading: 'Creating guild...',
success: 'Guild created successfully!',
error: 'Failed to create guild',
});
};
}
Custom Error Handling
const { error: toastError } = useToastMutations();
try {
await updateGuild(data).unwrap();
toast.success('Guild updated!');
} catch (error) {
toastError(error, 'Failed to update guild');
}
API Reference
useToast()
Returns an object with toast methods:
success(title: string, description?: string)- Show success toast (green)error(title: string, description?: string)- Show error toast (red)info(title: string, description?: string)- Show info toast (blue)warning(title: string, description?: string)- Show warning toast (yellow)loading(title: string, description?: string)- Show loading toast (no auto-dismiss)promise(promise, messages)- Show toast that updates based on promise state
useToastMutations()
Helper for RTK Query mutations:
toastPromise(promise, messages)- Automatically handles loading/success/errorsuccess(message, description)- Show success toasterror(error, fallbackMessage)- Extract error message and show toast
Configuration
Global Settings
Configured in ToastProvider:
<ToastProvider
placement="top-right" // Toast position
maxVisibleToasts={3} // Max toasts shown at once
toastProps={{
timeout: 4000, // Auto-dismiss after 4 seconds
hideCloseButton: false, // Show close button
}}
/>
Per-Toast Settings
Use HeroUI's addToast directly for advanced options:
import { addToast } from '@heroui/toast';
addToast({
title: 'Custom toast',
description: 'With custom settings',
color: 'primary',
timeout: 0, // No auto-dismiss
hideCloseButton: true, // No close button
hideIcon: false, // Show icon
});
Best Practices
DO ✅
- Use toasts for non-critical feedback
- Keep messages concise (1-2 lines)
- Use appropriate colors for context
- Use
toastPromisefor mutations - Provide actionable error messages
DON'T ❌
- Use toasts for critical errors (use modals instead)
- Show multiple toasts for the same action
- Use long messages (use description for details)
- Rely on toasts for permanent information
- Block user interaction with toasts
Examples
Archive Guild
const handleArchive = async (guildId: string) => {
await toastPromise(archiveGuild(guildId).unwrap(), {
loading: 'Archiving guild...',
success: 'Guild archived successfully',
error: 'Failed to archive guild',
});
};
Form Validation
const handleSubmit = async (data: FormData) => {
if (!data.name) {
toast.error('Validation failed', 'Guild name is required');
return;
}
await toastPromise(createGuild(data).unwrap(), {
loading: 'Creating guild...',
success: 'Guild created!',
error: 'Failed to create guild',
});
};
Manual Loading Control
const handleLongOperation = async () => {
const loadingToast = toast.loading('Processing...');
try {
await longOperation();
toast.dismiss(loadingToast);
toast.success('Operation complete!');
} catch (error) {
toast.dismiss(loadingToast);
toast.error('Operation failed');
}
};
Theming
Toasts automatically inherit HeroUI theme colors:
- Success: Green (
successcolor) - Error: Red (
dangercolor) - Info: Blue (
primarycolor) - Warning: Yellow (
warningcolor)
Colors adapt to light/dark mode automatically via HeroUI's theme system.
Troubleshooting
Toast Not Showing
- Verify
ToastProvideris rendered inmain.tsx - Check browser console for errors
- Ensure
@heroui/toastis installed
Wrong Colors
- Toasts use HeroUI's semantic colors
- Check theme configuration in
ThemeProvider - Verify HeroUI version compatibility
Toasts Stack Incorrectly
- Check
maxVisibleToastssetting - Verify
placementprop is valid - Clear browser cache and restart dev server