72bd43965f
把"手搓内联 class + Unicode 字符图标"换成统一组件与真实图标,为后续工业化打底。 - 依赖:装 lucide-react(描线图标,按需 tree-shake) - 令牌:tailwind.config 加语义色 brand/accent/success/warn/danger + 圆角档位; 强调色字面量(violet/cyan/emerald…)收敛到令牌,便于整体换肤 - primitives(src/ui,零重依赖自建):Button/Input/Textarea/Select/Field/Card/Panel/ Badge/Dot/Tabs/Skeleton/EmptyState/Dialog/Toast(+useToast)/cn,桶文件统一引入 - 迁移:TopBar/LeftNav/BottomDrawer + Home/Report/Runs/Kb/Placeholder/ExecTrace/ MemoryPanel/StudioView 全部换 primitives + lucide 图标;导航/能力卡/按钮告别 ▤◆▣▦ 等 Unicode 字符;错误改用全局 Toast;空状态用 EmptyState - App 包 ToastProvider 验证:tsc + vite build 通过;浏览器(Preview)走查工作台/报告页——真实图标、统一卡片/ 按钮/输入;跑报告端到端正常(执行轨迹 lucide 状态图标点亮、章节耗时/字数/检索片段、 完成弹 Toast + 下载 Word)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { X } from "lucide-react";
|
|
import { Button } from "./Button";
|
|
|
|
// Dialog 轻量模态:遮罩 + 居中卡片。open=false 不渲染。
|
|
export function Dialog({
|
|
open,
|
|
onClose,
|
|
title,
|
|
children,
|
|
footer,
|
|
}: {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
title: string;
|
|
children: ReactNode;
|
|
footer?: ReactNode;
|
|
}) {
|
|
if (!open) return null;
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/55 p-6" onClick={onClose}>
|
|
<div
|
|
className="w-full max-w-md rounded-lg border border-line bg-ink-900 shadow-card"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center border-b border-line px-4 py-3">
|
|
<h3 className="text-sm font-medium text-slate-100">{title}</h3>
|
|
<button onClick={onClose} className="ml-auto text-slate-500 hover:text-slate-300">
|
|
<X className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
<div className="px-4 py-4 text-sm text-slate-300">{children}</div>
|
|
{footer && <div className="flex justify-end gap-2 border-t border-line px-4 py-3">{footer}</div>}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ConfirmFooter 常用的取消/确认按钮组。
|
|
export function ConfirmFooter({ onCancel, onConfirm, confirmLabel = "确认", danger }: { onCancel: () => void; onConfirm: () => void; confirmLabel?: string; danger?: boolean }) {
|
|
return (
|
|
<>
|
|
<Button variant="ghost" size="sm" onClick={onCancel}>
|
|
取消
|
|
</Button>
|
|
<Button variant={danger ? "danger" : "primary"} size="sm" onClick={onConfirm}>
|
|
{confirmLabel}
|
|
</Button>
|
|
</>
|
|
);
|
|
}
|