PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.5
Tableberg – Simple Gutenberg Table Block v1.1.5
1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 0.5.7 All 42 releases
tableberg / src / components / CustomModal.tsx

CustomModal.tsx in Tableberg – Simple Gutenberg Table Block 1.1.5, at src/components/CustomModal.tsx

109 lines 3.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useEffect, useRef } from "react";
2 import { createPortal } from "react-dom";
3 import { Button } from "@wordpress/components";
4 import { __ } from "@wordpress/i18n";
5
6 interface CustomModalProps {
7 title: string;
8 onRequestClose: () => void;
9 className?: string;
10 isDismissible?: boolean;
11 shouldCloseOnClickOutside?: boolean;
12 children: React.ReactNode;
13 }
14
15 export default function CustomModal({
16 title,
17 onRequestClose,
18 className = "",
19 isDismissible = true,
20 shouldCloseOnClickOutside = true,
21 children,
22 }: CustomModalProps) {
23 const modalRef = useRef<HTMLDivElement>(null);
24 const previousActiveElement = useRef<HTMLElement | null>(null);
25
26 useEffect(() => {
27 // Store the previously focused element
28 previousActiveElement.current = document.activeElement as HTMLElement;
29
30 // Focus the modal
31 if (modalRef.current) {
32 modalRef.current.focus();
33 }
34
35 // Prevent body scrolling
36 document.body.style.overflow = "hidden";
37
38 // Handle ESC key
39 const handleEscape = (event: KeyboardEvent) => {
40 if (event.key === "Escape" && isDismissible) {
41 onRequestClose();
42 }
43 };
44
45 document.addEventListener("keydown", handleEscape);
46
47 return () => {
48 // Restore body scrolling
49 document.body.style.overflow = "";
50
51 // Restore focus to previous element
52 if (previousActiveElement.current) {
53 previousActiveElement.current.focus();
54 }
55
56 document.removeEventListener("keydown", handleEscape);
57 };
58 }, [isDismissible, onRequestClose]);
59
60 const handleBackdropClick = (event: React.MouseEvent) => {
61 if (
62 shouldCloseOnClickOutside &&
63 isDismissible &&
64 event.target === event.currentTarget
65 ) {
66 onRequestClose();
67 }
68 };
69
70 const modalContent = (
71 <div
72 className={`tableberg-custom-modal-backdrop ${className}`}
73 onClick={handleBackdropClick}
74 role="dialog"
75 aria-modal="true"
76 aria-labelledby="modal-title"
77 >
78 <div
79 ref={modalRef}
80 className="tableberg-custom-modal-container"
81 tabIndex={-1}
82 onClick={e => e.stopPropagation()}
83 >
84 <div className="tableberg-custom-modal-header">
85 <h2
86 id="modal-title"
87 className="tableberg-custom-modal-title"
88 >
89 {title}
90 </h2>
91 {isDismissible && (
92 <Button
93 variant="tertiary"
94 onClick={onRequestClose}
95 className="tableberg-custom-modal-close"
96 aria-label={__("Close modal", "tableberg")}
97 >
98 ×
99 </Button>
100 )}
101 </div>
102 <div className="tableberg-custom-modal-content">{children}</div>
103 </div>
104 </div>
105 );
106
107 return createPortal(modalContent, document.body);
108 }
109