33 lines
2.3 KiB
TypeScript
33 lines
2.3 KiB
TypeScript
import { useEffect, useRef } from "react";
|
||
import { Dialog } from "../../../ui/index.ts";
|
||
import { ErrorBoundary } from "../../../shell/ErrorBoundary.tsx";
|
||
import { IssueCard } from "./IssueCard.tsx";
|
||
|
||
// имя окна — ключ задачи; заголовок карточки (h2) подписывает окно через aria-labelledby
|
||
// окно карточки (design 13): <dialog> держит фокус и делает фон недоступным; Esc и щелчок по фону — onClose.
|
||
// Сами окно не закрываем: оно исчезает вместе с адресом карточки. Если браузер закрыл его сам (Esc без активации
|
||
// пользователя — cancel не отменяемый), открываем снова и просим закрытия по общему пути (блокировщик заметок).
|
||
export function IssueModal({ issueKey, onClose, onBack }: { issueKey: string; onClose: () => void; onBack?: () => void }) {
|
||
// I-2: закрывать щелчком по фону, только если и нажатие было на фоне — выделение текста, отпущенное за краем окна,
|
||
// даёт click на самом <dialog>, но нажатие было внутри содержимого
|
||
const downOnBackdrop = useRef(false);
|
||
useEffect(() => {
|
||
const prev = document.body.style.overflow;
|
||
document.body.style.overflow = "hidden"; // страница под окном не прокручивается
|
||
return () => { document.body.style.overflow = prev; };
|
||
}, []);
|
||
return (
|
||
<Dialog size="lg" className="issue-modal" label={issueKey} onClose={onClose} aria-labelledby="issue-modal-title"
|
||
onCancel={(e) => { if (e.cancelable) { e.preventDefault(); onClose(); } }}
|
||
onNativeClose={(e) => { const d = e.currentTarget; if (d.isConnected) { d.showModal(); onClose(); } }}
|
||
onPointerDown={(e) => { downOnBackdrop.current = e.target === e.currentTarget; }}
|
||
onClick={(e) => {
|
||
const fromBackdrop = downOnBackdrop.current;
|
||
downOnBackdrop.current = false;
|
||
if (e.target === e.currentTarget && fromBackdrop) onClose();
|
||
}}>
|
||
<ErrorBoundary key={issueKey}><IssueCard issueKey={issueKey} onClose={onClose} onBack={onBack} /></ErrorBoundary>
|
||
</Dialog>
|
||
);
|
||
}
|