React - Modal & Toast System
Overview
Estimated time: 25–35 minutes
Create a minimal modal manager and toast notifications with a simple context API.
Try it: Modal + Toasts
View source
const ToastCtx = React.createContext(null);
function ToastProvider({children}){
const [toasts, setToasts] = React.useState([]);
const api = React.useMemo(() => ({
push(msg){ const id = Math.random().toString(36).slice(2); setToasts(ts => [...ts, {id, msg}]); setTimeout(() => api.remove(id), 2500); },
remove(id){ setToasts(ts => ts.filter(t => t.id !== id)); }
}), []);
return (
<ToastCtx.Provider value={api}>
{children}
<div aria-live="polite" style={{position:'fixed', top:8, right:8, display:'grid', gap:8}}>
{toasts.map(t => <div key={t.id} style={{background:'#333', color:'#fff', padding:'8px 12px', borderRadius:8}}>{t.msg}</div>)}
</div>
</ToastCtx.Provider>
);
}
function useToast(){ return React.useContext(ToastCtx); }
function Modal({open, onClose, children}){
if (!open) return null;
return (
<div role="dialog" aria-modal="true" style={{position:'fixed', inset:0, background:'rgba(0,0,0,.35)', display:'grid', placeItems:'center'}} onClick={onClose}>
<div onClick={e => e.stopPropagation()} style={{background:'#fff', padding:12, borderRadius:8, minWidth:260}}>{children}</div>
</div>
);
}
function App(){
const toast = useToast();
const [open, setOpen] = React.useState(false);
return (
<div>
<button onClick={() => setOpen(true)}>Open modal</button>
<button onClick={() => toast.push('Saved successfully!')} style={{marginLeft:8}}>Show toast</button>
<Modal open={open} onClose={() => setOpen(false)}>
<h4>Modal</h4>
<p>Any content goes here.</p>
<button onClick={() => setOpen(false)}>Close</button>
</Modal>
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-modal-toasts')).render(<ToastProvider><App /></ToastProvider>);
Syntax primer
- Use context to expose a simple toast API to children.
- Modals can be implemented inline or via portals for layering.
Common pitfalls
- Forgetting to trap focus in complex modals—see Accessibility Deep Dive for focus trap.
Exercises
- Add a portal root and render modal and toasts into it.
- Support different toast types (success, error) and auto-dismiss durations.