Toast
The Toast component displays temporary notification messages to users, providing feedback for actions like adding items to cart or completing orders.
Overview
Located at src/components/toast/Toast.jsx, this component integrates with the useUIStore to display contextual notifications with automatic dismiss behavior and smooth animations.
Usage
The Toast component is rendered once in the Layout and controlled through the UI store:
import Toast from "../components/toast/Toast" ;
< Toast />
Trigger notifications from anywhere in the app:
import { useUIStore } from "../store/uiStore" ;
const showToast = useUIStore (( state ) => state . showToast );
// Show a notification
showToast ( "Product added to cart!" );
Component Structure
src/components/toast/Toast.jsx
const Toast = () => {
const toast = useUIStore (( state ) => state . toast );
const hideToast = useUIStore (( state ) => state . hideToast );
const [ isExiting , setIsExiting ] = useState ( false );
const [ prevToast , setPrevToast ] = useState ( null );
// Auto-hide after 2.5 seconds
useEffect (() => {
if ( ! toast ) return ;
const timer = setTimeout (() => {
setIsExiting ( true );
}, 2500 );
const cleanupTimer = setTimeout (() => {
hideToast ();
}, 2850 );
return () => {
clearTimeout ( timer );
clearTimeout ( cleanupTimer );
};
}, [ toast , hideToast ]);
if ( ! toast ) return null ;
const message = typeof toast === "string" ? toast : "" ;
const isSuccess = message . toLowerCase (). includes ( "added" );
const isError = message . toLowerCase (). includes ( "error" ) || message . includes ( "❌" );
return (
< div
className = { `custom-toast ${ isSuccess ? "success" : "" } ${ isError ? "error" : "" } ${ isExiting ? "toast-exit" : "" } ` }
role = "alert"
>
< div className = "d-flex align-items-center gap-2" >
{ isSuccess && < ShoppingCart size = { 20 } strokeWidth = { 2.5 } /> }
{ isError && < AlertCircle size = { 20 } strokeWidth = { 2.5 } /> }
< span > { message } </ span >
</ div >
</ div >
);
};
Features
Auto-Dismiss Automatically hides after 2.5 seconds
Contextual Icons Shows ShoppingCart or AlertCircle based on message type
Smooth Animations Entry and exit animations via CSS transitions
Type Detection Automatically detects success/error based on message content
Message Types
The toast automatically detects the type based on message content:
Success Messages
Any message containing “added” (case-insensitive):
showToast ( "Product added to cart!" ); // Green success toast with cart icon
Error Messages
Any message containing “error” or ”❌“:
showToast ( "Error loading products" ); // Red error toast with alert icon
showToast ( "❌ Failed to process order" ); // Red error toast
Default Messages
All other messages display without special styling:
showToast ( "Order placed successfully" ); // Default toast
Real-World Examples
Adding to Cart
src/components/productCard/ProductCard.jsx
import { useCartStore } from "../../store/useCartStore" ;
import { useUIStore } from "../../store/uiStore" ;
const addToCart = useCartStore (( state ) => state . addToCart );
const showToast = useUIStore (( state ) => state . showToast );
const handleAddToCart = ( e ) => {
e . stopPropagation ();
addToCart ( product );
showToast ( ` ${ product . title } added to cart` );
};
Order Confirmation
src/pages/checkoutpayment/CheckoutPayment.jsx
const showToast = useUIStore (( state ) => state . showToast );
const clearCart = useCartStore (( state ) => state . clearCart );
const handlePlaceOrder = ( e ) => {
e . preventDefault ();
const order = {
id: Date . now (),
items: cart ,
shipping ,
payment: { last4: payment . cardNumber . slice ( - 4 ) },
total ,
date: new Date (). toISOString (),
};
addOrder ( order );
clearCart ();
showToast ( "Order placed successfully! 🎉" );
navigate ( "/payment/success" );
};
Error Handling
const { data , isError , error } = useProducts ();
if ( isError ) {
showToast ( `❌ ${ error . message } ` );
}
Timing Configuration
The toast uses a two-phase dismissal:
Display phase : 2500ms (2.5 seconds)
Exit animation : 350ms
Total duration : 2850ms
src/components/toast/Toast.jsx:21-27
const timer = setTimeout (() => {
setIsExiting ( true ); // Start exit animation
}, 2500 );
const cleanupTimer = setTimeout (() => {
hideToast (); // Remove from DOM
}, 2850 );
The exit animation starts 350ms before the toast is removed to ensure smooth visual transitions.
CSS Styling
The component uses custom CSS classes defined in Toast.css:
.custom-toast {
position : fixed ;
top : 20 px ;
right : 20 px ;
z-index : 9999 ;
padding : 1 rem 1.5 rem ;
border-radius : 8 px ;
box-shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.15 );
animation : slideIn 0.3 s ease-out ;
}
.custom-toast.success {
background : #d4edda ;
color : #155724 ;
}
.custom-toast.error {
background : #f8d7da ;
color : #721c24 ;
}
.toast-exit {
animation : slideOut 0.3 s ease-in ;
}
Store Integration
The Toast component integrates with the UI store:
src/store/uiStore.js:19-30
toast : null ,
toastKey : 0 ,
showToast : ( message ) => {
set (( state ) => ({
toast: message ,
toastKey: state . toastKey + 1 ,
}));
},
hideToast : () => set ({ toast: null }),
The toastKey increments with each new toast, ensuring the component re-renders and restarts animations even if the same message is shown twice.
Accessibility
The component includes proper ARIA attributes:
< div role = "alert" >
{ /* Toast content */ }
</ div >
The role="alert" attribute ensures screen readers announce the notification immediately.
Best Practices
Toast messages should be brief (under 50 characters) to ensure they’re read before auto-dismissing.
Use “added” for success messages and “error” for failures to ensure automatic type detection works correctly.
Only show toasts for important user actions. Avoid showing toasts for every minor interaction.
Ensure 2.5 seconds is enough time for users to read your longest messages. Adjust if needed.
UI Store - Manages toast state and controls
ProductCard - Uses toast for cart notifications
Navbar - Container for Toast component via Layout