Skip to content

Commit f6f1b20

Browse files
committed
style: export modal
1 parent 16eda66 commit f6f1b20

3 files changed

Lines changed: 81 additions & 58 deletions

File tree

src/components/shared/PdfExport.tsx

Lines changed: 76 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState } from "react";
22
import { useTranslations } from "@/i18n/compat/client";
3-
import { Download, Loader2, ChevronDown } from "lucide-react";
3+
import { Download, Loader2, ChevronDown, ShieldCheck } from "lucide-react";
44
import { useResumeStore } from "@/store/useResumeStore";
55
import { Button } from "@/components/ui/button";
66
import { exportResumeAsJson, exportResumeAsMarkdown, exportToPdf } from "@/utils/export";
@@ -46,28 +46,32 @@ const ExportCard = ({
4646
if (!isLoading) onClick();
4747
}}
4848
className={cn(
49-
"group relative flex flex-col justify-center overflow-hidden p-6 pl-[130px] min-h-[140px] rounded-3xl border bg-card text-card-foreground shadow-sm transition-all duration-500",
50-
isLoading ? "opacity-70 cursor-not-allowed" : cn("cursor-pointer hover:shadow-xl active:scale-[0.98] hover:-translate-y-1", hoverBorderClass)
49+
"group relative flex flex-col justify-center overflow-hidden p-6 pl-[136px] min-h-[130px] rounded-3xl border border-border/50 bg-card text-card-foreground shadow-sm transition-all duration-500",
50+
isLoading ? "opacity-70 cursor-not-allowed" : cn("cursor-pointer hover:shadow-2xl active:scale-[0.98] hover:-translate-y-1 hover:bg-muted/10", hoverBorderClass)
5151
)}
5252
>
53+
{/* 顶部内发光高光,增加卡片立体感 */}
54+
<div className="absolute inset-0 rounded-3xl ring-1 ring-inset ring-white/10 pointer-events-none mix-blend-overlay opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
55+
5356
{/* 底部环境光晕,让图标色渗入背景 */}
5457
<div className={cn(
5558
"absolute inset-0 pointer-events-none transition-opacity duration-500 bg-gradient-to-r to-transparent",
5659
isLoading ? "opacity-50" : "opacity-0 group-hover:opacity-100",
5760
bgGradientClass
5861
)} />
5962

63+
{/* 调整后的图标层:完全收入卡片内部,尺寸克制 */}
6064
<div className={cn(
61-
"absolute -left-6 top-1/2 -translate-y-1/2 w-40 h-40 transition-transform duration-500 will-change-transform drop-shadow-xl pointer-events-none",
62-
isLoading ? "-rotate-12 scale-[1.08] opacity-80" : "-rotate-12 group-hover:scale-[1.08]"
65+
"absolute left-6 top-1/2 -translate-y-1/2 w-24 h-24 transition-transform duration-500 will-change-transform drop-shadow-xl pointer-events-none",
66+
isLoading ? "-rotate-6 scale-[1.05] opacity-80" : "-rotate-6 group-hover:scale-[1.1] group-hover:-rotate-3"
6367
)}>
6468
<Icon className="w-full h-full object-contain" isLoading={isLoading} />
6569
</div>
6670

67-
{/* 文本内容说明 (Z-indexed above icon) */}
71+
{/* 文本内容说明 */}
6872
<div className="relative z-10 flex flex-col pointer-events-none">
69-
<h3 className="font-bold text-[17px] mb-2 tracking-tight text-foreground/90 transition-colors">{title}</h3>
70-
<p className="text-[13px] text-muted-foreground/80 leading-relaxed line-clamp-3 group-hover:text-muted-foreground transition-colors">
73+
<h3 className="font-semibold text-[17px] mb-1.5 tracking-tight text-foreground/90 transition-colors">{title}</h3>
74+
<p className="text-[13px] text-muted-foreground/75 leading-relaxed line-clamp-3 group-hover:text-muted-foreground/90 transition-colors">
7175
{description}
7276
</p>
7377
</div>
@@ -190,53 +194,70 @@ const PdfExport = ({ children }: { children?: React.ReactNode }) => {
190194
)}
191195
</DialogTrigger>
192196

193-
<DialogContent className="max-w-4xl gap-8 p-8 sm:rounded-2xl border-none shadow-2xl bg-gradient-to-b from-background to-muted/20">
194-
<DialogHeader className="gap-2">
195-
<DialogTitle className="text-2xl font-bold flex items-center gap-3">
196-
{t("modal.title")}
197-
</DialogTitle>
198-
<DialogDescription className="text-sm text-muted-foreground/80 mt-1">
199-
{t("modal.subtitle")}
200-
</DialogDescription>
201-
</DialogHeader>
202-
203-
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
204-
<ExportCard
205-
icon={PdfGlassIcon}
206-
title={t("button.exportPdf")}
207-
description={t("modal.pdfDesc")}
208-
isLoading={isExporting}
209-
onClick={handleExport}
210-
bgGradientClass="from-rose-500/10 dark:from-rose-500/20"
211-
hoverBorderClass="hover:border-rose-500/40 hover:ring-1 hover:ring-rose-500/20"
212-
/>
213-
<ExportCard
214-
icon={PrintGlassIcon}
215-
title={t("button.print")}
216-
description={t("modal.printDesc")}
217-
isLoading={isPrinting}
218-
onClick={handlePrint}
219-
bgGradientClass="from-sky-500/10 dark:from-sky-500/20"
220-
hoverBorderClass="hover:border-sky-500/40 hover:ring-1 hover:ring-sky-500/20"
221-
/>
222-
<ExportCard
223-
icon={JsonGlassIcon}
224-
title={t("button.exportJson")}
225-
description={t("modal.jsonDesc")}
226-
isLoading={isExportingJson}
227-
onClick={handleJsonExport}
228-
bgGradientClass="from-amber-500/10 dark:from-amber-500/20"
229-
hoverBorderClass="hover:border-amber-500/40 hover:ring-1 hover:ring-amber-500/20"
230-
/>
231-
<ExportCard
232-
icon={MarkdownGlassIcon}
233-
title={t("button.exportMarkdown")}
234-
description={t("modal.markdownDesc")}
235-
isLoading={isExportingMarkdown}
236-
onClick={handleMarkdownExport}
237-
bgGradientClass="from-indigo-500/10 dark:from-indigo-500/20"
238-
hoverBorderClass="hover:border-indigo-500/40 hover:ring-1 hover:ring-indigo-500/20"
239-
/>
197+
<DialogContent className="max-w-4xl gap-0 p-0 sm:rounded-[2rem] border border-border/60 shadow-[0_20px_60px_-15px_rgba(0,0,0,0.1)] bg-background overflow-hidden">
198+
{/* 头部区域:带精美网格和高光 */}
199+
<div className="relative p-8 pb-6 border-b border-border/40 bg-muted/10">
200+
{/* SaaS 网格底纹背景 */}
201+
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none [mask-image:radial-gradient(ellipse_60%_50%_at_50%_0%,#000_70%,transparent_100%)]" />
202+
203+
<DialogHeader className="relative gap-2">
204+
<DialogTitle className="text-2xl font-bold tracking-tight">
205+
{t("modal.title")}
206+
</DialogTitle>
207+
<DialogDescription className="text-[15px] text-muted-foreground/80 mt-1">
208+
{t("modal.subtitle")}
209+
</DialogDescription>
210+
</DialogHeader>
211+
</div>
212+
213+
{/* 卡片展示区域 */}
214+
<div className="p-8 bg-background">
215+
<div className="grid grid-cols-1 md:grid-cols-2 gap-5 relative">
216+
<ExportCard
217+
icon={PdfGlassIcon}
218+
title={t("button.exportPdf")}
219+
description={t("modal.pdfDesc")}
220+
isLoading={isExporting}
221+
onClick={handleExport}
222+
bgGradientClass="from-rose-500/10 dark:from-rose-500/20"
223+
hoverBorderClass="hover:border-rose-500/40 hover:ring-1 hover:ring-rose-500/20"
224+
/>
225+
<ExportCard
226+
icon={PrintGlassIcon}
227+
title={t("button.print")}
228+
description={t("modal.printDesc")}
229+
isLoading={isPrinting}
230+
onClick={handlePrint}
231+
bgGradientClass="from-sky-500/10 dark:from-sky-500/20"
232+
hoverBorderClass="hover:border-sky-500/40 hover:ring-1 hover:ring-sky-500/20"
233+
/>
234+
<ExportCard
235+
icon={JsonGlassIcon}
236+
title={t("button.exportJson")}
237+
description={t("modal.jsonDesc")}
238+
isLoading={isExportingJson}
239+
onClick={handleJsonExport}
240+
bgGradientClass="from-amber-500/10 dark:from-amber-500/20"
241+
hoverBorderClass="hover:border-amber-500/40 hover:ring-1 hover:ring-amber-500/20"
242+
/>
243+
<ExportCard
244+
icon={MarkdownGlassIcon}
245+
title={t("button.exportMarkdown")}
246+
description={t("modal.markdownDesc")}
247+
isLoading={isExportingMarkdown}
248+
onClick={handleMarkdownExport}
249+
bgGradientClass="from-indigo-500/10 dark:from-indigo-500/20"
250+
hoverBorderClass="hover:border-indigo-500/40 hover:ring-1 hover:ring-indigo-500/20"
251+
/>
252+
</div>
253+
254+
{/* 隐私保护横幅 */}
255+
<div className="mt-6 flex items-center gap-2 p-3 sm:px-4 rounded-xl bg-emerald-50 dark:bg-emerald-500/10 border border-emerald-100 dark:border-emerald-500/20 text-emerald-600 dark:text-emerald-400">
256+
<ShieldCheck className="w-4 h-4 shrink-0" />
257+
<p className="text-[13px] font-medium">
258+
{t("modal.privacyNotice")}
259+
</p>
260+
</div>
240261
</div>
241262
</DialogContent>
242263
</Dialog>

src/i18n/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@
260260
"pdfDesc": "High-precision rendering with 100% format accuracy. Recommended for job applications.",
261261
"printDesc": "Save via system print dialog. Use as a fallback or for custom margins.",
262262
"jsonDesc": "Export your resume data as JSON to backup or transfer between devices.",
263-
"markdownDesc": "Convert to plain Markdown text for easy sharing with AI models."
263+
"markdownDesc": "Convert to plain Markdown text for easy sharing with AI models.",
264+
"privacyNotice": "Magic Resume promise never to collect, upload, or store any of your resume data. Your privacy is fully protected."
264265
},
265266
"button": {
266267
"export": "Export",

src/i18n/locales/zh.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,9 @@
260260
"subtitle": "选择您希望导出简历的格式",
261261
"pdfDesc": "通过高精度渲染生成,100% 还原格式,简历投递首选。",
262262
"printDesc": "调用系统打印工具另存为 PDF,当主渲染拥堵或需手动干预边距时的备用方案。",
263-
"jsonDesc": "保存您的配置档案副本。日后换设备或清理缓存后可用于一键无损导入恢复进度。",
264-
"markdownDesc": "转换为方便复用的极简文本标记语言档案,方便后续向大模型或其他文本编辑器中快速粘贴经历。"
263+
"jsonDesc": "保存您的配置档案副本。日后更换设备或清理缓存后,可使用此文件一键无损导入恢复进度。",
264+
"markdownDesc": "转换为极简的文本标记语言文件,方便快速粘贴给各种 AI 模型或是其他文本编辑器。",
265+
"privacyNotice": "魔方简历承诺绝不收集、上传或存储您的任何简历数据,您的隐私完全受到保护。"
265266
},
266267
"button": {
267268
"export": "导出",

0 commit comments

Comments
 (0)