diff --git a/docs/popup-design-philosophy.md b/docs/popup-design-philosophy.md new file mode 100644 index 0000000..c2f5ab0 --- /dev/null +++ b/docs/popup-design-philosophy.md @@ -0,0 +1,15 @@ +# Design Philosophy: Clean Modernity + +## 视觉哲学宣言 + +**简约而不简单**。现代设计的本质不是添加,而是减法。每一个元素的存在都应有其意义,每一处空白都是设计的呼吸。去除一切不必要的装饰,让功能本身成为美学。 + +**清晰的视觉层次**。用户视线应自然流动,从最重要的元素流向次要元素。通过尺寸、颜色、间距和对比度建立层次,无需多余标注。信息自明,用户无需思考。 + +**克制的色彩运用**。以单色或双色调为主,点缀恰到好处的强调色。色彩用于引导注意力和表达状态,而非装饰。柔和的灰度背景承载内容,明亮的强调色突出行动。 + +**微妙的圆角与阴影**。圆润的边角传递友好与亲和,恰到好处的阴影创造深度与层次。避免生硬的直角和夸张的投影,追求自然的光影效果。 + +**精致的细节把控**。即使在16像素的图标中,每一个像素都经过考量。按钮的点击区域、字体的行高、元素的对齐——这些看不见的细节决定了整体的品质感。博物馆级的工艺标准意味着卓越。 + +**留白的艺术**。空间本身就是一种元素。足够的留白让内容得以呼吸,让界面看起来从容不迫。拥挤的界面传达焦虑,宽敞的界面传递自信。 diff --git a/src/index.css b/src/index.css index a437d90..df28026 100644 --- a/src/index.css +++ b/src/index.css @@ -11,3 +11,55 @@ body { padding: 0; width: 320px; } + +/* 动画 */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +.animate-fade-in { + animation: fadeIn 0.2s ease-out; +} + +.animate-scale-in { + animation: scaleIn 0.2s ease-out; +} + +/* 自定义滚动条 */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: #d1d5db; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #9ca3af; +} + +.dark ::-webkit-scrollbar-thumb { + background: #4b5563; +} + +.dark ::-webkit-scrollbar-thumb:hover { + background: #6b7280; +} diff --git a/src/popup/Popup.tsx b/src/popup/Popup.tsx index 17d76bb..b4cbc7d 100644 --- a/src/popup/Popup.tsx +++ b/src/popup/Popup.tsx @@ -68,7 +68,6 @@ export function Popup() { }); await copyToClipboard(markdown); showStatus('success', '已复制到剪贴板!'); - // 1秒后关闭弹窗 setTimeout(() => { window.close(); }, 1000); @@ -89,8 +88,6 @@ export function Popup() { const blob = new Blob([markdown], { type: 'text/markdown;charset=utf-8' }); const url = URL.createObjectURL(blob); - - // 使用chrome.downloads API const filename = `${extractedContent.title.replace(/[<>:"/\\|?*]/g, '_').substring(0, 100)}.md`; await chrome.downloads.download({ url: url, @@ -100,7 +97,6 @@ export function Popup() { URL.revokeObjectURL(url); showStatus('success', '开始下载...'); - // 1秒后关闭弹窗 setTimeout(() => { window.close(); }, 1000); @@ -141,51 +137,74 @@ export function Popup() { if (settingsLoading) { return ( -
-
+
+
); } return ( -
- {/* 标题 */} -
- - - - -

ReadMD

+
+ {/* 头部 */} +
+
+
+ + + + + + +
+
+

ReadMD

+

网页转 Markdown

+
+
- {/* 提取按钮 */} - + {/* 主要内容区 */} +
+ {/* 状态消息 */} + {status.message && ( +
+ {status.message} +
+ )} - {/* 状态消息 */} - {status.message && ( -
- {status.message} -
- )} + {/* 提取按钮 */} + - {/* 分隔线 */} -
+ {/* 选项面板 */} + +
- {/* 选项面板 */} - + {/* 页脚 */} +
+ +
{/* 预览弹窗 */} {showPreview && extractedContent && ( @@ -196,20 +215,6 @@ export function Popup() { onDownload={handleDownload} /> )} - - {/* 页脚 */} -
); } diff --git a/src/popup/components/ExtractButton.tsx b/src/popup/components/ExtractButton.tsx index d148c0a..1bf893e 100644 --- a/src/popup/components/ExtractButton.tsx +++ b/src/popup/components/ExtractButton.tsx @@ -9,23 +9,23 @@ export function ExtractButton({ loading, onExtract, mode, onModeChange }: Extrac return (
{/* 提取模式切换 */} -
+
diff --git a/src/popup/components/OptionsPanel.tsx b/src/popup/components/OptionsPanel.tsx index 76a951d..0632aeb 100644 --- a/src/popup/components/OptionsPanel.tsx +++ b/src/popup/components/OptionsPanel.tsx @@ -7,52 +7,104 @@ interface OptionsPanelProps { export function OptionsPanel({ settings, onSettingsChange }: OptionsPanelProps) { return ( -
-

导出选项

+
+

导出选项

- +
+ {/* 包含标题 */} + - + {/* 包含原文链接 */} + - + {/* 简化模式 */} + +
+ {/* 图片处理 */}
-
); diff --git a/src/popup/components/PreviewModal.tsx b/src/popup/components/PreviewModal.tsx index 4909c6a..ea3dfc2 100644 --- a/src/popup/components/PreviewModal.tsx +++ b/src/popup/components/PreviewModal.tsx @@ -20,72 +20,97 @@ export function PreviewModal({ content, onClose, onCopy, onDownload }: PreviewMo }); return ( -
-
+
+
{/* 标题栏 */} -
-

预览

+
+
+
+ + + +
+
+

预览

+

{content.title}

+
+
{/* 内容预览 */} -
-
{content.title}
- +
{/* 切换按钮 */} -
+
{showRaw ? ( -
+            
               {markdown}
             
) : (
.+$/gm, '') // 移除引用 - .replace(/```[\s\S]*?```/g, '[代码块]') // 简化代码块 - .replace(/\n/g, '
') // 换行 + .replace(/^# .+$/m, '') + .replace(/> .+$/gm, '') + .replace(/```[\s\S]*?```/g, '[代码块]') + .replace(/\n/g, '
') }} /> )}
{/* 操作按钮 */} -
+