feat: add delete confirmation dialog to DetailPanel
Uses the existing ConfirmDialog component (native <dialog> element styled like the app). Clicking Delete Track now opens a confirmation modal instead of instantly deleting. Also cleaned up ConfirmDialog to use React.Ref<HTMLDialogElement> for React 19 compatibility, and removed unused ConfirmDialog import from App.tsx.
This commit is contained in:
1 parent
fb3c3c7c05
commit
b514e282a1
3 files changed
+111
-3
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
interface Props {
|
||||
/** The <dialog> element ref — call ref.current?.showModal() to open. */
|
||||
ref?: React.Ref<HTMLDialogElement>
|
||||
/** Title shown in the dialog header. */
|
||||
title: string
|
||||
/** Body text explaining what will happen. */
|
||||
message: string
|
||||
/** Label for the confirm button. Defaults to "Confirm". */
|
||||
confirmLabel?: string
|
||||
/** Called when the user confirms. */
|
||||
onConfirm: () => void
|
||||
/** Optional: called when the user cancels. */
|
||||
onCancel?: () => void
|
||||
/** Danger style — makes confirm button red. Default true. */
|
||||
danger?: boolean
|
||||
}
|
||||
|
||||
export default function ConfirmDialog({
|
||||
ref,
|
||||
title,
|
||||
message,
|
||||
confirmLabel = 'Confirm',
|
||||
onConfirm,
|
||||
onCancel,
|
||||
danger = true,
|
||||
}: Props) {
|
||||
useEffect(() => {
|
||||
const dialog = ref && 'current' in ref ? ref.current : null
|
||||
if (!dialog) return
|
||||
|
||||
const handleClose = () => onCancel?.()
|
||||
dialog.addEventListener('close', handleClose)
|
||||
return () => dialog.removeEventListener('close', handleClose)
|
||||
}, [ref, onCancel])
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (ref && 'current' in ref && ref.current) ref.current.close('confirm')
|
||||
onConfirm()
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
if (ref && 'current' in ref && ref.current) ref.current.close('cancel')
|
||||
}
|
||||
|
||||
return (
|
||||
<dialog
|
||||
ref={ref}
|
||||
className="bg-kithara-panel border border-white/10 rounded-lg text-white backdrop:bg-black/60 backdrop:backdrop-blur-sm max-w-sm w-full p-0"
|
||||
onClick={(e) => {
|
||||
if (ref && 'current' in ref && e.target === ref.current) handleCancel()
|
||||
}}
|
||||
>
|
||||
<form method="dialog" className="p-5">
|
||||
<h3 className="text-base font-semibold mb-2">{title}</h3>
|
||||
<p className="text-sm text-kithara-muted mb-5">{message}</p>
|
||||
<div className="flex justify-end gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCancel}
|
||||
className="px-3 py-1.5 text-sm rounded bg-white/5 border border-white/10 text-kithara-muted hover:text-white hover:bg-white/10 transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleConfirm}
|
||||
className={`px-3 py-1.5 text-sm rounded font-medium transition-colors ${
|
||||
danger
|
||||
? 'bg-red-500/80 hover:bg-red-500 text-white'
|
||||
: 'bg-kithara-accent hover:bg-kithara-accent/80 text-white'
|
||||
}`}
|
||||
>
|
||||
{confirmLabel}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user