import React, { useEffect, useRef, useCallback, useState } from 'react'; import { createPortal } from 'react-dom'; import { X } from 'lucide-react'; interface MobileDrawerProps { isOpen: boolean; onClose: () => void; position: 'left' | 'right'; children: React.ReactNode; title?: string; } export function MobileDrawer({ isOpen, onClose, position, children, title }: MobileDrawerProps): React.ReactElement | null { const [isClosing, setIsClosing] = useState(false); const drawerRef = useRef(null); const previousActiveElement = useRef(null); const handleClose = useCallback(() => { setIsClosing(true); setTimeout(() => { setIsClosing(false); onClose(); }, 300); }, [onClose]); useEffect(() => { if (isOpen) { previousActiveElement.current = document.activeElement as HTMLElement; drawerRef.current?.focus(); } else if (previousActiveElement.current) { previousActiveElement.current.focus(); } }, [isOpen]); useEffect(() => { const handleEscape = (event: KeyboardEvent) => { if (event.key === 'Escape' && isOpen && !isClosing) { handleClose(); } }; document.addEventListener('keydown', handleEscape); return () => document.removeEventListener('keydown', handleEscape); }, [isOpen, isClosing, handleClose]); useEffect(() => { if (isOpen) { document.body.style.overflow = 'hidden'; } return () => { document.body.style.overflow = ''; }; }, [isOpen]); useEffect(() => { if (!isOpen || !drawerRef.current) return; const drawer = drawerRef.current; const focusableElements = drawer.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; const handleTabKey = (event: KeyboardEvent) => { if (event.key !== 'Tab') return; if (event.shiftKey) { if (document.activeElement === firstElement) { event.preventDefault(); lastElement?.focus(); } } else { if (document.activeElement === lastElement) { event.preventDefault(); firstElement?.focus(); } } }; drawer.addEventListener('keydown', handleTabKey); return () => drawer.removeEventListener('keydown', handleTabKey); }, [isOpen]); const handleBackdropClick = (event: React.MouseEvent) => { if (event.target === event.currentTarget && !isClosing) { handleClose(); } }; if (!isOpen && !isClosing) return null; const slideAnimation = isClosing ? position === 'left' ? 'drawer-slide-out-left' : 'drawer-slide-out-right' : position === 'left' ? 'drawer-slide-in-left' : 'drawer-slide-in-right'; const backdropAnimation = isClosing ? 'drawer-backdrop-out' : 'drawer-backdrop-in'; const positionClasses = position === 'left' ? 'left-0' : 'right-0'; const content = (
{title && (

{title}

)} {!title &&
}
{children}
); return createPortal(content, document.body); }