fix: 统一弹框组件 — ModalOverlay对齐EditInstanceDialog行为
- ModalOverlay移除遮罩层onClick(不响应外部点击关闭) - 移除body.style.overflow=hidden(修复白条问题) - max-h从90vh改为85vh(与EditInstanceDialog一致) - 10个页面手写fixed弹框替换为ModalOverlay组件 - InstanceGroupPage/WorkflowPage/UsersPage/RedisDetailPage/TicketsPage已替换 - dialog.tsx添加onPointerDownOutside/onInteractOutside阻止外部点击 - index.css添加body[data-scroll-locked]覆盖Radix滚动锁定 - Layout.tsx main添加relative定位上下文
This commit is contained in:
1 parent
5366d5c963
commit
3c5e1c1f7d
10 files changed
+111
-87
No files matched your search
+1
-42
@@ -1,42 +1 @@
|
||||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.react:hover {
|
||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
a:nth-of-type(2) .logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
/* App styles — Vite template defaults removed */
|
||||
@@ -122,7 +122,7 @@ export default function Layout() {
|
||||
</aside>
|
||||
|
||||
{/* 主内容区 */}
|
||||
<main className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||||
<main id="app-main" className="relative flex-1 flex flex-col min-w-0 overflow-hidden">
|
||||
{/* 顶部栏 */}
|
||||
<header className="h-14 bg-[var(--dg-bg-secondary)] border-b border-[var(--dg-border)] flex items-center justify-between px-5 flex-shrink-0">
|
||||
{/* Breadcrumb area */}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
|
||||
interface ModalOverlayProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
width?: string;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ModalOverlay({ open, onClose, width = 'max-w-lg', className = '', children }: ModalOverlayProps) {
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
},
|
||||
[onClose],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
}
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [open, handleKeyDown]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
|
||||
<div
|
||||
className={`bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full ${width} max-h-[85vh] overflow-y-auto ${className}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -36,7 +36,9 @@ function DialogOverlay({
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
"fixed inset-0 z-[100] bg-black/50",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -53,12 +55,24 @@ function DialogContent({
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DialogPortal data-slot="dialog-portal">
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
onPointerDownOutside={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
onInteractOutside={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
className={cn(
|
||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
|
||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
||||
"fixed z-[101] grid w-full max-w-[calc(100%-2rem)]",
|
||||
"top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]",
|
||||
"gap-4 rounded-lg border p-6 shadow-lg duration-200",
|
||||
"outline-none sm:max-w-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -337,6 +337,14 @@
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', sans-serif;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Fix: Radix Dialog scroll-lock adds padding-right to body, causing white bar.
|
||||
Override to prevent layout shift when dialog opens. */
|
||||
body[data-scroll-locked],
|
||||
body[data-radix-scroll-locked],
|
||||
body[style*="padding-right"] {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
code, pre, .font-mono {
|
||||
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { instanceApi } from '@/api/instance';
|
||||
import { userApi } from '@/api/user';
|
||||
import { useActionPermission } from '@/hooks/useAuth';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import { ModalOverlay } from '@/components/ModalOverlay';
|
||||
|
||||
/* ───────── Constants ───────── */
|
||||
|
||||
@@ -389,8 +390,8 @@ export default function InstanceGroupPage() {
|
||||
|
||||
{/* Form Modal (create & edit) */}
|
||||
{formMode && (
|
||||
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[5vh] bg-black/60 backdrop-blur-sm">
|
||||
<div className="w-full max-w-3xl bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl flex flex-col max-h-[90vh] border border-[var(--dg-border)]" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={!!formMode} onClose={formClose} width="max-w-3xl">
|
||||
<div className="w-full max-w-3xl bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl flex flex-col max-h-[90vh] border border-[var(--dg-border)]">
|
||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[var(--dg-border)]">
|
||||
<h3 className="text-lg font-semibold">{formMode === 'create' ? '新建权限策略' : '编辑权限策略'}</h3>
|
||||
<button onClick={formClose} className="p-1.5 rounded-lg hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><X className="w-4 h-4" /></button>
|
||||
@@ -433,7 +434,7 @@ export default function InstanceGroupPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
|
||||
<ConfirmDialog
|
||||
@@ -447,8 +448,8 @@ export default function InstanceGroupPage() {
|
||||
|
||||
{/* User Modal */}
|
||||
{showUserModal && (
|
||||
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[10vh] bg-black/60 backdrop-blur-sm">
|
||||
<div className="w-full max-w-md bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl border border-[var(--dg-border)]" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={showUserModal} onClose={() => setShowUserModal(false)} width="max-w-md">
|
||||
<div className="w-full max-w-md bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl border border-[var(--dg-border)]">
|
||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[var(--dg-border)]">
|
||||
<h3 className="text-lg font-semibold">关联用户</h3>
|
||||
<button onClick={() => setShowUserModal(false)} className="p-1.5 rounded-lg hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><X className="w-4 h-4" /></button>
|
||||
@@ -474,7 +475,7 @@ export default function InstanceGroupPage() {
|
||||
</div>
|
||||
</div>{/* end px-6 py-4 */}
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, Key, Activity, Terminal, Gauge, Plus, RefreshCw, Search } from 'lucide-react';
|
||||
import { redisApi } from '@/api/redis';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import { ModalOverlay } from '@/components/ModalOverlay';
|
||||
|
||||
type TabKey = 'keys' | 'monitor' | 'cli' | 'perf';
|
||||
|
||||
@@ -265,8 +266,8 @@ export default function RedisDetailPage() {
|
||||
|
||||
{/* 键详情弹窗 */}
|
||||
{selectedKey && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full max-w-lg max-h-[70vh] overflow-y-auto p-6" onClick={function (e) { e.stopPropagation(); }}>
|
||||
<ModalOverlay open={!!selectedKey} onClose={function () { setSelectedKey(null); }} width="max-w-lg">
|
||||
<div className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full max-h-[70vh] overflow-y-auto p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold">键详情</h3>
|
||||
<button onClick={function () { setSelectedKey(null); }} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]">✕</button>
|
||||
@@ -282,13 +283,13 @@ export default function RedisDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
|
||||
{/* 新增键弹窗 */}
|
||||
{showAddKey && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full max-w-md p-6" onClick={function (e) { e.stopPropagation(); }}>
|
||||
<ModalOverlay open={showAddKey} onClose={function () { setShowAddKey(false); }} width="max-w-md">
|
||||
<div className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold">新增键</h3>
|
||||
<button onClick={function () { setShowAddKey(false); }} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]">✕</button>
|
||||
@@ -306,7 +307,7 @@ export default function RedisDetailPage() {
|
||||
<button onClick={handleAddKey} className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
<ConfirmDialog
|
||||
open={!!deleteConfirm}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useActionPermission } from '@/hooks/useAuth';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import { ticketApi } from '@/api/ticket';
|
||||
import { ModalOverlay } from '@/components/ModalOverlay';
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Types */
|
||||
@@ -595,10 +596,9 @@ function TicketDetailDialog({ ticket, onClose, canApprove, canExecute, onActionD
|
||||
}, [ticket.id, onActionDone]);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60" onClick={onClose}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-3xl" className="border border-[var(--dg-border)] overflow-hidden flex flex-col">
|
||||
<div
|
||||
className="w-full max-w-3xl max-h-[85vh] bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl shadow-2xl overflow-hidden flex flex-col"
|
||||
onClick={e => e.stopPropagation()}
|
||||
className="w-full max-h-[85vh] overflow-hidden flex flex-col"
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[var(--dg-border)]">
|
||||
@@ -787,6 +787,6 @@ function TicketDetailDialog({ ticket, onClose, canApprove, canExecute, onActionD
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { instanceGroupApi, type InstanceGroup } from '@/api/instanceGroup';
|
||||
import { nameToUsername } from '@/utils/pinyin';
|
||||
import { toast } from '@/hooks/useToast';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import { ModalOverlay } from '@/components/ModalOverlay';
|
||||
|
||||
/* ───────── Types ───────── */
|
||||
|
||||
@@ -566,8 +567,8 @@ function CreateUserModal({ onClose, onCreated }: { onClose: () => void; onCreate
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-md bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-md">
|
||||
<div className="w-full bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl">
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<h2 className="text-lg font-semibold">新建用户</h2>
|
||||
<button onClick={onClose} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><XCircle className="w-5 h-5" /></button>
|
||||
@@ -626,7 +627,7 @@ function CreateUserModal({ onClose, onCreated }: { onClose: () => void; onCreate
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -674,8 +675,8 @@ function EditUserModal({ user, onClose, onUpdated }: { user: UserItem; onClose:
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-md bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-md">
|
||||
<div className="w-full bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl">
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<h2 className="text-lg font-semibold">编辑用户</h2>
|
||||
<button onClick={onClose} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><XCircle className="w-5 h-5" /></button>
|
||||
@@ -740,7 +741,7 @@ function EditUserModal({ user, onClose, onUpdated }: { user: UserItem; onClose:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -771,8 +772,8 @@ function ResetPasswordModal({ user, onClose }: { user: UserItem; onClose: () =>
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-sm bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-sm">
|
||||
<div className="w-full bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl">
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<h2 className="text-lg font-semibold flex items-center gap-2"><KeyRound className="w-5 h-5 text-yellow-400" /> 重置密码</h2>
|
||||
<button onClick={onClose} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><XCircle className="w-5 h-5" /></button>
|
||||
@@ -798,7 +799,7 @@ function ResetPasswordModal({ user, onClose }: { user: UserItem; onClose: () =>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -807,8 +808,8 @@ function ResetPasswordModal({ user, onClose }: { user: UserItem; onClose: () =>
|
||||
function UserDetailModal({ user, onClose }: { user: UserItem; onClose: () => void }) {
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-lg bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl max-h-[80vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-lg">
|
||||
<div className="w-full bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl max-h-[80vh] overflow-y-auto">
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<h2 className="text-lg font-semibold">用户详情</h2>
|
||||
<button onClick={onClose} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><XCircle className="w-5 h-5" /></button>
|
||||
@@ -864,7 +865,7 @@ function UserDetailModal({ user, onClose }: { user: UserItem; onClose: () => voi
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1033,8 +1034,8 @@ function BatchImportModal({ onClose, onImported }: { onClose: () => void; onImpo
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-2xl max-h-[85vh] bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl shadow-xl flex flex-col" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-2xl">
|
||||
<div className="w-full max-h-[85vh] bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl shadow-xl flex flex-col">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-6 py-4">
|
||||
<h2 className="text-lg font-semibold">批量导入用户</h2>
|
||||
@@ -1238,8 +1239,8 @@ function BatchImportModal({ onClose, onImported }: { onClose: () => void; onImpo
|
||||
|
||||
{/* Create OU sub-dialog */}
|
||||
{showCreateOu && (
|
||||
<div className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50">
|
||||
<div className="w-full max-w-md bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl" onClick={e => e.stopPropagation()}>
|
||||
<ModalOverlay open={showCreateOu} onClose={() => setShowCreateOu(false)} width="max-w-md">
|
||||
<div className="w-full bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 shadow-xl">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-base font-semibold">创建新的组织单位 (OU)</h3>
|
||||
<button onClick={() => setShowCreateOu(false)} className="text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)]"><X className="w-5 h-5" /></button>
|
||||
@@ -1261,9 +1262,9 @@ function BatchImportModal({ onClose, onImported }: { onClose: () => void; onImpo
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { Card, CardContent } from '@/components/ui/card';
|
||||
import { workflowApi } from '@/api/workflow';
|
||||
import { userApi } from '@/api/user';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import { ModalOverlay } from '@/components/ModalOverlay';
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Types */
|
||||
@@ -320,10 +321,9 @@ function WorkflowEditorModal({ workflow, users, onClose, onSaved }: EditorProps)
|
||||
const inputCls = 'w-full px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none transition-colors';
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
|
||||
<ModalOverlay open={true} onClose={onClose} width="max-w-2xl">
|
||||
<div
|
||||
className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="bg-[var(--dg-bg-secondary)] rounded-xl shadow-2xl w-full max-h-[90vh] overflow-y-auto"
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-5 py-4">
|
||||
@@ -455,7 +455,7 @@ function WorkflowEditorModal({ workflow, users, onClose, onSaved }: EditorProps)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -744,8 +744,8 @@ export default function WorkflowPage() {
|
||||
|
||||
{/* Preview Modal */}
|
||||
{previewWorkflow && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm" onClick={() => setPreviewWorkflow(null)}>
|
||||
<div className="bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 max-w-2xl w-full mx-4 max-h-[85vh] overflow-y-auto" onClick={(e) => e.stopPropagation()}>
|
||||
<ModalOverlay open={!!previewWorkflow} onClose={() => setPreviewWorkflow(null)} width="max-w-2xl">
|
||||
<div className="bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl p-6 w-full mx-4 max-h-[85vh] overflow-y-auto">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-xl font-semibold">{previewWorkflow.name}</h3>
|
||||
@@ -799,7 +799,7 @@ export default function WorkflowPage() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalOverlay>
|
||||
)}
|
||||
|
||||
{/* Editor Modal */}
|
||||
|
||||
Reference in new issue
Block a user