Hooks
useDismiss
Закрытие слоя по клику мимо и Escape — с оглядкой на диалоги.
Закрытие всплывающего слоя по клику мимо и по Escape. Небольшой хук, но с одной оговоркой, ради которой он и существует.
Пример
import { useRef, useState } from "react";
import { useDismiss } from "@toimetdev/pathlogs-hooks";
function Popover() {
const [open, setOpen] = useState(false);
const box = useRef<HTMLDivElement>(null);
useDismiss(box, { enabled: open, onDismiss: () => setOpen(false) });
return (
<div ref={box} className="relative">
<button onClick={() => setOpen((v) => !v)}>Открыть</button>
{open && <div className="absolute">…</div>}
</div>
);
}Параметры
| Проп | Тип | По умолчанию | Описание |
|---|---|---|---|
enabled* | boolean | — | Пока false, слушатели не вешаются вовсе. |
onDismiss* | () => void | — | Что сделать. Читается в момент события. |
escape | boolean | true | Закрывать по Escape. |
outsideClick | boolean | true | Закрывать по клику мимо. |
blockedBy | string | "[data-pl-overlay]" | Селектор «поверх меня открыто что-то ещё». Пока такой элемент есть в документе, закрытие пропускается. |
enabled*booleanПока false, слушатели не вешаются вовсе.
onDismiss*() => voidЧто сделать. Читается в момент события.
escapebooleanпо умолчанию: true
Закрывать по Escape.
outsideClickbooleanпо умолчанию: true
Закрывать по клику мимо.
blockedBystringпо умолчанию: "[data-pl-overlay]"
Селектор «поверх меня открыто что-то ещё». Пока такой элемент есть в документе, закрытие пропускается.
Диалог поверх меню
Вот ради чего нужен blockedBy. Типичная разметка: триггер диалога лежит внутри выпадающего меню, а сам диалог рендерится порталом в body.
<Menu>
<MenuItem onClick={() => setConfirmOpen(true)}>Удалить проект</MenuItem>
<ConfirmDialog open={confirmOpen} … /> {/* портал в body */}
</Menu>Клик по пункту меню открывает диалог. Если бы меню закрылось от этого же клика, оно размонтировало бы триггер — а вместе с ним и диалог, который в нём объявлен. Окно не успело бы появиться: пользователь увидел бы, что «кнопка не работает».
Если у вас свои модальные окна, укажите их селектор: blockedBy: ".my-modal-backdrop". Пустая строка отключает проверку.