Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { PropsWithChildren, useEffect, useId, useRef } from 'react'
import { FocusOn } from 'react-focus-on'
import ActionButton, { ActionButtonProps } from './ActionButton'
export interface ModalProps extends PropsWithChildren {
actionButtons: ActionButtonProps[]
header: string
onClose: EventListener
open: boolean
}
const Modal = ({
actionButtons,
children,
header,
onClose,
open,
}: ModalProps) => {
const dialogRef = useRef<HTMLDialogElement>(null)
const id = useId()
useEffect(() => {
if (open) {
dialogRef.current?.showModal()
} else E{
dialogRef.current?.close()
}
}, [open])
useEffect(() => {
const el = dialogRef.current
el?.addEventListener('close', onClose)
return () => {
el?.removeEventListener('close', onClose)
}
}, [onClose])
// "Confirm" button of form triggers "close" on dialog because of [method="dialog"]
return (
<dialog
ref={dialogRef}
className="w-full border-none bg-transparent p-1 backdrop:bg-black backdrop:bg-opacity-80 md:w-2/3 lg:w-2/5"
>
<FocusOn enabled={open}>
<section
data-autofocus
tabIndex={-1}
className="rounded-md bg-white ring-2 ring-gray-modal"
aria-describedby={`${id}-modal-header`}
>
<header
id={`${id}-modal-header`}
className="rounded-t-md border-b border-black bg-blue-deep p-3 text-white"
>
<h1>{header}</h1>
</header>
<div id={`${id}-modal-desc`} className="p-3">
{children}
</div>
<div className="flex justify-end gap-2 border-t border-gray-modal p-2">
{actionButtons.map((actionButtonProps) => (
<ActionButton
key={actionButtonProps.text}
{...actionButtonProps}
/>
))}
</div>
</section>
</FocusOn>
</dialog>
)
}
export default Modal
|