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

  1. Add a portal root and render modal and toasts into it.
  2. Support different toast types (success, error) and auto-dismiss durations.