diff --git a/src/frontend/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx b/src/frontend/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx
index 2e053f81d..48cb09f6c 100644
--- a/src/frontend/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx
+++ b/src/frontend/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx
@@ -14,13 +14,11 @@ import {
Label,
} from '~/components/ui';
import { useDeleteSharedLinkMutation, useSharedLinksQuery } from '~/hooks/queries/data-provider';
-import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
import { useLocalize, usePrefersMobileLayout } from '~/hooks';
import DataTable from '~/components/ui/DataTable';
import { NotificationSeverity } from '~/common';
-import { useToastContext } from '~/Providers';
+import { useToastContext, useConfirm } from '~/Providers';
import { formatDate } from '~/utils';
-import { Spinner } from '~/components/svg';
const PAGE_SIZE = 25;
@@ -37,7 +35,6 @@ export default function SharedLinks() {
const { showToast } = useToastContext();
const isSmallScreen = usePrefersMobileLayout();
const [queryParams, setQueryParams] = useState(DEFAULT_PARAMS);
- const [isDeleteOpen, setIsDeleteOpen] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, refetch, isLoading } =
@@ -86,8 +83,6 @@ export default function SharedLinks() {
const deleteMutation = useDeleteSharedLinkMutation({
onSuccess: async () => {
- setIsDeleteOpen(false);
- setDeleteRow(null);
await refetch();
},
onError: (error) => {
@@ -144,14 +139,22 @@ export default function SharedLinks() {
await fetchNextPage();
}, [fetchNextPage, hasNextPage, isFetchingNextPage]);
- const [deleteRow, setDeleteRow] = useState(null);
-
- const confirmDelete = useCallback(() => {
- if (deleteRow) {
- handleDelete([deleteRow]);
- }
- setIsDeleteOpen(false);
- }, [deleteRow, handleDelete]);
+ const confirm = useConfirm();
+ const handleDeleteClick = useCallback(
+ async (row: SharedLinkItem) => {
+ const ok = await confirm({
+ variant: 'destructive',
+ title: localize('com_ui_delete_shared_link'),
+ description: `${localize('com_ui_delete_confirm')} "${row.title}"`,
+ confirmText: localize('com_ui_delete'),
+ });
+ if (!ok) {
+ return;
+ }
+ handleDelete([row]);
+ },
+ [confirm, localize, handleDelete],
+ );
const columns = useMemo(
() => [
@@ -247,10 +250,7 @@ export default function SharedLinks() {
+/** Identical body for every shell so only the shell itself differs. */
+const demoBody = (
+
+
+ 这里是弹窗正文示例。观察内边距、行距与正文和标题/按钮的间距。
+
+
+
);
+/** Small reference demo of the finalized confirm dialog, for shell comparison. */
+function ConfirmReferenceDemo() {
+ const confirm = useConfirm();
+ return (
+
+ );
+}
+
export function ModalSection() {
return (
- 现状有 两套并行体系:A 套 Dialog(毛玻璃遮罩 z-100)与 B 套{' '}
- OriginalDialog / OG(纯深色遮罩 z-50)。逐个打开对比背景暗度、模糊、层级。
+ 2026-07-09 重新盘点:全站普通弹窗共 5 个并行体系、约 64 个业务文件
+ 。二次确认期已把 B 套壳对齐 C 套视觉,但 A 套(原语直接拼 22 处 + 模板 3
+ 处)与手拼 AlertDialog(7 处)仍是另外两种壳。逐个打开对比,定统一标准。
>
}
>
- {/* Difference table */}
-
+ {/* ① Population overview */}
+
+ ① 用量盘子(当前精确扫描,排除 ui/ 与画廊)
+
+
22(最大人群),
+ '新页面为主:知识库 8、订阅 2、审批/通知/账号/分享/appChat…(含 MainLayout 全局弹窗)',
+ ],
+ [
+ 'A 套 · 模板',
+ 'DialogTemplate',
+ '3',
+ 'EditPresetDialog、PresetItems、ContextButton(后者在 SidePanel 死树)',
+ ],
+ [
+ 'B 套 · 模板',
+ 'OGDialogTemplate',
+ '16(原 25,确认迁移后)',
+ '书签/导出/SetKey/归档/Agent 面板…(其中 SidePanel 死树约 6 处);壳已对齐 C 套',
+ ],
+ [
+ 'B 套 · 原语直接拼',
+ 'OGDialog + OGDialogContent 手拼',
+ '16',
+ '设置(账号/数据)、Prompts、文件预览、ShareAgent…;壳同上(已对齐 C 套)',
+ ],
+ [
+ '手拼 AlertDialog',
+ 'AlertDialogContent + 自拼头尾',
+ '7',
+ '频道成员 2、爬取系 4、灵思 TaskModeInput(部分带确认性质,本期一并处理)',
+ ],
+ [
+ 'C 套 · useConfirm(参照)',
+ 'ConfirmContext(AlertDialog 底层)',
+ '26(已收敛 ✅)',
+ '二次确认已定稿的视觉基准:圆角16 / p-5 / 灰底毛玻璃 —— Modal 壳的天然候选',
+ ],
]}
/>
-
- {/* A-set raw primitives */}
-
-
+ {/* ④ Decision checklist */}
+
④ 待设计师定夺
+
+
+ -
+ 遮罩:A 套浅黑毛玻璃(black/40+blur) vs B/C 套灰白毛玻璃(gray-500/90+blur)?
+ (纯深色 black/80 已在二次确认期淘汰)
+
+ -
+ 圆角:8px(A 套 / AlertDialog) vs 16px(B/C 套)?移动端是否保留直角/贴底?
+
+ -
+ 内边距:p-5(20px,A/B/C) vs p-6(24px,AlertDialog)?header/body/footer 间距(当前统一 gap-4)?
+
+ -
+ 标题:font-semibold(A 套) vs font-medium(B/C 套)?
+
+ -
+ 关闭按钮 ×:样式与位置(当前 A/B 内置右上小 ×,AlertDialog 各页自拼)?
+
+ -
+ footer 按钮:普通弹窗的取消/确定用 Button 组件(outline+default) 还是 C
+ 套确认弹窗那对(白底描边 + danger/primary)?按钮间距 gap-2 vs gap-3?
+
+ -
+ 层级:z-50 / z-[100] / z-[110] 三档并存,统一到几?(需盘 Drawer/Sheet/Popover 的层级关系)
+
+ -
+ 原语收敛:A 套 22 处直拼是最大人群 —— 是把 A 套壳改成标准(业务零改动),还是逐批迁 B 套?
+
+
+
);
}
diff --git a/src/frontend/client/src/pages/standaloneChat/components/GuestConvoItem.tsx b/src/frontend/client/src/pages/standaloneChat/components/GuestConvoItem.tsx
index bdedf4f0c..4d6dbd59c 100644
--- a/src/frontend/client/src/pages/standaloneChat/components/GuestConvoItem.tsx
+++ b/src/frontend/client/src/pages/standaloneChat/components/GuestConvoItem.tsx
@@ -7,8 +7,8 @@ import { useLocalize } from '~/hooks';
import { cn } from '~/utils';
import type { AppConversation } from '~/@types/app';
-import { DropdownPopup, OGDialog, Label } from '~/components';
-import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
+import { DropdownPopup } from '~/components';
+import { useConfirm } from '~/Providers';
import TodayItemIcon from '~/components/ui/icon/TodayItem';
type GuestConvoItemProps = {
@@ -29,7 +29,7 @@ export function GuestConvoItem({ conv, isActive, onClick, onRename, onDelete }:
const [isPopoverActive, setIsPopoverActive] = useState(false);
const [renaming, setRenaming] = useState(false);
const [titleInput, setTitleInput] = useState(conv.title);
- const [showDeleteDialog, setShowDeleteDialog] = useState(false);
+ const confirm = useConfirm();
const inputRef = useRef
(null);
const menuId = useId();
@@ -83,10 +83,18 @@ export function GuestConvoItem({ conv, isActive, onClick, onRename, onDelete }:
[conv.title],
);
- const confirmDelete = useCallback(() => {
+ const handleDeleteClick = useCallback(async () => {
+ const ok = await confirm({
+ variant: 'destructive',
+ title: localize('com_ui_delete_conversation'),
+ description: `${localize('com_ui_delete_confirm')} "${conv.title}"`,
+ confirmText: localize('com_ui_delete'),
+ });
+ if (!ok) {
+ return;
+ }
onDelete(conv.id);
- setShowDeleteDialog(false);
- }, [conv.id, onDelete]);
+ }, [confirm, localize, conv.title, conv.id, onDelete]);
return (
{
- if (renaming || isPopoverActive || showDeleteDialog) return;
+ if (renaming || isPopoverActive) return;
onClick();
}}
>
@@ -174,7 +182,7 @@ export function GuestConvoItem({ conv, isActive, onClick, onRename, onDelete }:
label: localize('com_ui_delete'),
onClick: () => {
setIsPopoverActive(false);
- setShowDeleteDialog(true);
+ handleDeleteClick();
},
icon:
,
hideOnClick: false,
@@ -184,31 +192,6 @@ export function GuestConvoItem({ conv, isActive, onClick, onRename, onDelete }:
]}
menuId={menuId}
/>
-
- {/* Delete confirmation dialog */}
- {showDeleteDialog && (
-
-
-
-
-
-
- }
- selection={{
- selectHandler: confirmDelete,
- selectClasses: 'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 text-white',
- selectText: localize('com_ui_delete'),
- }}
- />
-
- )}
>
)}