Реалізація модальних вікон (Modal/Popup) на вебсайті
Модальні вікна мають багато прихованих проблем: управління фокусом, скролл позаду модалі, z-index конфлікти, анімації, мобільний клавіатурний зсув. Нативний <dialog> розв'язує більшість без JS.
Нативний <dialog>: правильна основа
Модаль з showModal() блокує фон через ::backdrop. Використовуємо createPortal для React. Закриття на Escape або клік на фон. Focus trap вбудований.
import { useEffect, useRef, ReactNode } from 'react'
import { createPortal } from 'react-dom'
export function Modal({
isOpen, onClose, title, children,
size = 'md',
closeOnBackdrop = true,
}: ModalProps) {
const dialogRef = useRef<HTMLDialogElement>(null)
useEffect(() => {
const dialog = dialogRef.current
if (!dialog) return
if (isOpen) {
dialog.showModal()
document.body.style.overflow = 'hidden'
} else {
dialog.close()
document.body.style.overflow = ''
}
}, [isOpen])
return createPortal(
<dialog ref={dialogRef} className={`modal modal--${size}`}>
<div className="modal__content">
{title && <h2 className="modal__title">{title}</h2>}
<div className="modal__body">{children}</div>
</div>
</dialog>,
document.body
)
}
CSS анімація для входу та виходу модалі з плавними переходами.
Focus Trap
Утримуємо фокус всередину модалі під час взаємодії. Нативний dialog розбирається з цим автоматично.
Bottom Sheet для мобільних
Позиціюємо fixed від низу з safe-area inset регулюванням для iOS.
Терміни
Базова модаль з анімацією — 3–4 години. React компонент з порталом, focus trap — 1 день. Повна система з confirm/alert API, стеком підтримки — 1,5–2 дні.







