Files
vps-tracker/apps/web/src/components/confirm-dialog.tsx
T
DenozordecandCursor 42c567e5b5
Docker / build (push) Failing after 20s
fix(spaces): не закрывать ConfirmDialog при удалении из меню
Диалог вынесен из DropdownMenu, иначе размонтировался вместе с меню.

Co-authored-by: Cursor <[email protected]>
2026-07-19 18:14:44 +07:00

78 lines
2.1 KiB
TypeScript

import { useState, type ReactElement, type ReactNode } from 'react'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from '@cfdm/ui/components/alert-dialog'
interface ConfirmDialogProps {
/** Optional when using controlled `open` (e.g. open from DropdownMenu) */
trigger?: ReactElement
title: string
description?: ReactNode
confirmLabel?: string
cancelLabel?: string
destructive?: boolean
/** Called after dialog closes (next tick) — safe for file pickers */
onConfirm: () => void
open?: boolean
onOpenChange?: (open: boolean) => void
}
export function ConfirmDialog({
trigger,
title,
description,
confirmLabel = 'Подтвердить',
cancelLabel = 'Отмена',
destructive,
onConfirm,
open: openProp,
onOpenChange: onOpenChangeProp,
}: ConfirmDialogProps) {
const [uncontrolledOpen, setUncontrolledOpen] = useState(false)
const isControlled = openProp !== undefined
const open = isControlled ? openProp : uncontrolledOpen
function setOpen(next: boolean) {
if (!isControlled) setUncontrolledOpen(next)
onOpenChangeProp?.(next)
}
function handleConfirm() {
setOpen(false)
// Close AlertDialog before opening native file picker / async work
queueMicrotask(() => {
onConfirm()
})
}
return (
<AlertDialog open={open} onOpenChange={setOpen}>
{trigger ? <AlertDialogTrigger render={trigger} /> : null}
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{title}</AlertDialogTitle>
{description ? <AlertDialogDescription>{description}</AlertDialogDescription> : null}
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{cancelLabel}</AlertDialogCancel>
<AlertDialogAction
variant={destructive ? 'destructive' : 'default'}
onClick={handleConfirm}
>
{confirmLabel}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}