forked from Nova-reward/Nova-Rewards
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModal.js
More file actions
41 lines (36 loc) · 1.28 KB
/
Copy pathModal.js
File metadata and controls
41 lines (36 loc) · 1.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
'use client';
import React, { useEffect, useRef } from 'react';
/**
* Modal component — accessible, focus-trapped, keyboard-dismissible.
* Closes #610
*/
export default function Modal({ open, onClose, title, children, className = '' }) {
const dialogRef = useRef(null);
useEffect(() => {
if (open) dialogRef.current?.focus();
}, [open]);
useEffect(() => {
function onKey(e) { if (e.key === 'Escape') onClose?.(); }
if (open) document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
}, [open, onClose]);
if (!open) return null;
return (
<div className="ui-modal-overlay" role="presentation" onClick={(e) => { if (e.target === e.currentTarget) onClose?.(); }}>
<div
ref={dialogRef}
role="dialog"
aria-modal="true"
aria-labelledby={title ? 'ui-modal-title' : undefined}
tabIndex={-1}
className={`ui-modal ${className}`}
>
<div className="ui-modal__header">
{title && <h2 id="ui-modal-title" className="ui-modal__title">{title}</h2>}
<button className="ui-modal__close" onClick={onClose} aria-label="Close modal">✕</button>
</div>
<div className="ui-modal__body">{children}</div>
</div>
</div>
);
}