68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import { useEffect, useRef } from 'react'
|
|
|
|
type Props = {
|
|
open: boolean
|
|
title: string
|
|
message: React.ReactNode
|
|
onClose: () => void
|
|
}
|
|
|
|
function CheckIcon() {
|
|
return (
|
|
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.6" />
|
|
<path
|
|
d="m8.2 12.3 2.6 2.6 5-5.4"
|
|
stroke="currentColor"
|
|
strokeWidth="1.6"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export function SuccessModal({ open, title, message, onClose }: Props) {
|
|
const closeRef = useRef<HTMLButtonElement>(null)
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
|
|
closeRef.current?.focus()
|
|
|
|
function handleKeyDown(event: KeyboardEvent) {
|
|
if (event.key === 'Escape') onClose()
|
|
}
|
|
|
|
document.addEventListener('keydown', handleKeyDown)
|
|
return () => document.removeEventListener('keydown', handleKeyDown)
|
|
}, [open, onClose])
|
|
|
|
if (!open) return null
|
|
|
|
return (
|
|
<div className="confirm-dialog-backdrop" onClick={onClose}>
|
|
<div
|
|
className="confirm-dialog success-modal"
|
|
role="alertdialog"
|
|
aria-modal="true"
|
|
aria-labelledby="success-modal-title"
|
|
onClick={(event) => event.stopPropagation()}
|
|
>
|
|
<div className="success-modal-icon">
|
|
<CheckIcon />
|
|
</div>
|
|
<h2 id="success-modal-title" className="confirm-dialog-title">
|
|
{title}
|
|
</h2>
|
|
<p className="confirm-dialog-message">{message}</p>
|
|
<div className="confirm-dialog-actions">
|
|
<button ref={closeRef} type="button" className="btn btn-primary" onClick={onClose}>
|
|
OK
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|