📌Problem Statement
Design a modal/dialog system that's accessible and reusable.
📌Requirements
📌Portal Implementation
const Portal = ({ children }) => { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); return () => setMounted(false); }, []); if (!mounted) return null; return createPortal( children, document.getElementById('modal-root') );};📌Modal Component
const Modal = ({ isOpen, onClose, title, children }) => { const modalRef = useRef(); const previousFocus = useRef(); useEffect(() => { if (isOpen) { previousFocus.current = document.activeElement; modalRef.current?.focus(); document.body.style.overflow = 'hidden'; } return () => { document.body.style.overflow = ''; previousFocus.current?.focus(); }; }, [isOpen]); useEffect(() => { const handleEscape = (e) => { if (e.key === 'Escape') onClose(); }; if (isOpen) { document.addEventListener('keydown', handleEscape); } return () => document.removeEventListener('keydown', handleEscape); }, [isOpen, onClose]); if (!isOpen) return null; return ( <Portal> <div className="modal-overlay" onClick={onClose}> <div ref={modalRef} className="modal-content" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="modal-title" tabIndex={-1} > <h2 id="modal-title">{title}</h2> {children} <button onClick={onClose}>Close</button> </div> </div> </Portal> );};📌Focus Trap
const useFocusTrap = (ref, isActive) => { useEffect(() => { if (!isActive) return; const element = ref.current; const focusableElements = element.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; const handleTab = (e) => { if (e.key !== 'Tab') return; if (e.shiftKey) { if (document.activeElement === firstElement) { e.preventDefault(); lastElement.focus(); } } else { if (document.activeElement === lastElement) { e.preventDefault(); firstElement.focus(); } } }; element.addEventListener('keydown', handleTab); return () => element.removeEventListener('keydown', handleTab); }, [ref, isActive]);};📌Modal Stack Management
const ModalContext = createContext();const ModalProvider = ({ children }) => { const [modals, setModals] = useState([]); const open = (modalId, props) => { setModals(prev => [...prev, { id: modalId, props }]); }; const close = (modalId) => { setModals(prev => prev.filter(m => m.id !== modalId)); }; return ( <ModalContext.Provider value={{ open, close, modals }}> {children} {modals.map((modal, index) => ( <Modal key={modal.id} zIndex={100 + index} {...modal.props} /> ))} </ModalContext.Provider> );};Asked at Google, Facebook, and Airbnb interviews.