fix: confirm dialog is now a compact popup, not full-screen overlay
- Removed full-screen overlay backdrop (bg-black/95 + backdrop-blur) - Dialog is centered via fixed left-1/2 top-1/2 -translate - Compact design: max-w-sm, smaller text, smaller buttons - Uses admin theme vars (admin-surface, admin-border, admin-text) - Smooth scale+fade animation without overlay
This commit is contained in:
1 parent
93601e58e0
commit
844add04ef
1 file changed
+16
-40
@@ -5,7 +5,6 @@ import { AnimatePresence, motion } from "motion/react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { modalContentVariants, modalOverlayVariants } from "@/lib/motion";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export type ConfirmDialogProps = {
|
||||
@@ -20,10 +19,6 @@ export type ConfirmDialogProps = {
|
||||
onConfirm: () => void | Promise<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Portal-based confirm modal (not Dialog.Root) so it can safely stack
|
||||
* above Visual Manager / other Base UI dialogs without nested-root bugs.
|
||||
*/
|
||||
export function ConfirmDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
@@ -62,65 +57,47 @@ export function ConfirmDialog({
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
const isOpen = open;
|
||||
|
||||
return createPortal(
|
||||
<AnimatePresence>
|
||||
{isOpen ? (
|
||||
{open ? (
|
||||
<motion.div
|
||||
key="confirm-overlay"
|
||||
className="fixed inset-0 z-[200] flex items-center justify-center p-4"
|
||||
variants={modalOverlayVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Dismiss"
|
||||
className="absolute inset-0 bg-black/95"
|
||||
disabled={isLoading}
|
||||
onClick={() => {
|
||||
if (!isLoading) onOpenChange(false);
|
||||
}}
|
||||
/>
|
||||
<motion.div
|
||||
key="confirm-content"
|
||||
key="confirm-popup"
|
||||
role="alertdialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="confirm-dialog-title"
|
||||
aria-describedby="confirm-dialog-desc"
|
||||
className="relative z-10 w-full max-w-md rounded-xl border-2 border-primary/40 bg-surface p-6 text-card-foreground shadow-[0_0_60px_-10px_rgba(245,158,11,0.3)]"
|
||||
variants={modalContentVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
className="fixed left-1/2 top-1/2 z-[200] w-full max-w-sm -translate-x-1/2 -translate-y-1/2 rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-5 shadow-2xl"
|
||||
initial={{ opacity: 0, scale: 0.95, y: -4 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.95, y: -4 }}
|
||||
transition={{ duration: 0.15, ease: "easeOut" }}
|
||||
>
|
||||
<div className="flex flex-col gap-2 text-left">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-2.5">
|
||||
{variant === "danger" && (
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-destructive/15">
|
||||
<AlertTriangle className="h-5 w-5 text-destructive" />
|
||||
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--admin-error)]/15">
|
||||
<AlertTriangle className="h-4 w-4 text-[var(--admin-error)]" />
|
||||
</div>
|
||||
)}
|
||||
<h2
|
||||
id="confirm-dialog-title"
|
||||
className="text-lg font-semibold leading-none"
|
||||
className="text-sm font-semibold text-[var(--admin-text)]"
|
||||
>
|
||||
{title}
|
||||
</h2>
|
||||
</div>
|
||||
<p
|
||||
id="confirm-dialog-desc"
|
||||
className="text-sm text-muted-foreground"
|
||||
className="text-xs text-[var(--admin-text-muted)]"
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
|
||||
<div className="mt-4 flex justify-end gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={isLoading}
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
@@ -129,11 +106,11 @@ export function ConfirmDialog({
|
||||
<Button
|
||||
type="button"
|
||||
variant={variant === "danger" ? "destructive" : "default"}
|
||||
size="sm"
|
||||
disabled={isLoading}
|
||||
onClick={handleConfirm}
|
||||
className={cn(
|
||||
variant === "danger" &&
|
||||
"bg-destructive text-destructive-foreground",
|
||||
variant === "danger" && "bg-[var(--admin-error)] text-white",
|
||||
)}
|
||||
autoFocus
|
||||
>
|
||||
@@ -141,7 +118,6 @@ export function ConfirmDialog({
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
) : null}
|
||||
</AnimatePresence>,
|
||||
document.body,
|
||||
|
||||
Reference in new issue
Block a user