sdlc-hub/web/src/modules/jira/issues/IssueModal.tsx

33 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
}