feat: 重新设计现代化图标系统

新增 Icons.tsx 统一图标组件(25 个图标):
- AppIcon: 渐变蓝色圆角矩形 + M↓ 符号
- 工具栏: FolderOpen, Save, SplitView, EditMode, PreviewMode, Moon, Sun
- 标签栏: Close, Plus
- 侧边栏: Folder, File, ChevronRight, FolderPlus
- 搜索栏: ChevronUp, ChevronDown, X
- 拖拽: UploadCloud
- 导航: ArrowUp, ArrowDown
- 欢迎: WelcomeFile, WelcomeNew

设计风格:
- 线性图标(stroke-based),统一 1.75px 线宽
- 圆角风格,现代科技感
- 蓝色主色调渐变应用图标
- 部分图标添加微妙的填充细节(opacity 0.3-0.4)

更新组件:
- Toolbar: 使用 FolderOpen/Save/SplitView/EditMode/PreviewMode/Moon/Sun
- TabBar: 使用 Close/Plus
- Sidebar: 使用 FolderPlus/File/Folder/ChevronRight
- SearchBar: 使用 ChevronUp/ChevronDown/X
- WelcomeScreen: 使用 AppIcon/WelcomeFile/WelcomeNew
- DropOverlay: 使用 UploadCloud
This commit is contained in:
thzxx
2026-05-27 21:44:26 +08:00
parent 70dff0cf01
commit db94ecfad0
7 changed files with 283 additions and 108 deletions
+251
View File
@@ -0,0 +1,251 @@
import React from 'react'
// 统一图标 Props
interface IconProps {
size?: number
className?: string
style?: React.CSSProperties
}
const defaultProps: Partial<IconProps> = { size: 18 }
// ===== 应用图标 =====
export function AppIcon({ size = 80 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* 背景圆角矩形 */}
<rect x="4" y="4" width="72" height="72" rx="16" fill="url(#app-bg)" stroke="url(#app-stroke)" strokeWidth="2"/>
{/* Markdown M↓ 符号 */}
<path d="M22 28v24M22 52V40l8-8 8 8v12M46 28l6 12 6-12v24" stroke="white" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"/>
{/* 底部装饰线 */}
<rect x="16" y="60" width="48" height="3" rx="1.5" fill="rgba(255,255,255,0.3)"/>
<defs>
<linearGradient id="app-bg" x1="4" y1="4" x2="76" y2="76" gradientUnits="userSpaceOnUse">
<stop stopColor="#3B82F6"/>
<stop offset="1" stopColor="#1D4ED8"/>
</linearGradient>
<linearGradient id="app-stroke" x1="4" y1="4" x2="76" y2="76" gradientUnits="userSpaceOnUse">
<stop stopColor="#60A5FA"/>
<stop offset="1" stopColor="#2563EB"/>
</linearGradient>
</defs>
</svg>
)
}
// ===== 工具栏图标 =====
export function FolderOpen({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M5 19a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v1"/>
<path d="M20.5 15H5a2 2 0 0 0-2 2l1.5 7h18l2-7a2 2 0 0 0-2-2h-2.5z" fill="none"/>
<path d="M12 11h4" strokeDasharray="2 2"/>
</svg>
)
}
export function Save({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
<polyline points="17 21 17 13 7 13 7 21"/>
<polyline points="7 3 7 8 15 8"/>
</svg>
)
}
export function SplitView({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="3" width="18" height="18" rx="3"/>
<line x1="12" y1="3" x2="12" y2="21"/>
<rect x="5" y="7" width="5" height="2" rx="1" fill="currentColor" opacity="0.4"/>
<rect x="5" y="11" width="3" height="2" rx="1" fill="currentColor" opacity="0.3"/>
<rect x="14" y="7" width="5" height="2" rx="1" fill="currentColor" opacity="0.4"/>
<rect x="14" y="11" width="3" height="2" rx="1" fill="currentColor" opacity="0.3"/>
</svg>
)
}
export function EditMode({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
<circle cx="18" cy="6" r="1" fill="currentColor"/>
</svg>
)
}
export function PreviewMode({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
<circle cx="12" cy="12" r="3"/>
<circle cx="12" cy="12" r="1" fill="currentColor"/>
</svg>
)
}
export function Moon({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
<circle cx="19" cy="5" r="1" fill="currentColor" opacity="0.5"/>
</svg>
)
}
export function Sun({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="5"/>
<circle cx="12" cy="12" r="2" fill="currentColor" opacity="0.3"/>
<line x1="12" y1="1" x2="12" y2="3"/>
<line x1="12" y1="21" x2="12" y2="23"/>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
<line x1="1" y1="12" x2="3" y2="12"/>
<line x1="21" y1="12" x2="23" y2="12"/>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
</svg>
)
}
// ===== 标签栏图标 =====
export function Close({ size = 10 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
)
}
export function Plus({ size = 14 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<line x1="12" y1="5" x2="12" y2="19"/>
<line x1="5" y1="12" x2="19" y2="12"/>
</svg>
)
}
// ===== 侧边栏图标 =====
export function Folder({ size = 14 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
<line x1="9" y1="13" x2="15" y2="13" opacity="0.4"/>
</svg>
)
}
export function File({ size = 14 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
<line x1="8" y1="13" x2="16" y2="13" opacity="0.4"/>
<line x1="8" y1="17" x2="13" y2="17" opacity="0.3"/>
</svg>
)
}
export function ChevronRight({ size = 10 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
)
}
export function FolderPlus({ size = 14 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
<line x1="12" y1="11" x2="12" y2="17"/>
<line x1="9" y1="14" x2="15" y2="14"/>
</svg>
)
}
// ===== 搜索栏图标 =====
export function ChevronUp({ size = 12 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<polyline points="18 15 12 9 6 15"/>
</svg>
)
}
export function ChevronDown({ size = 12 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<polyline points="6 9 12 15 18 9"/>
</svg>
)
}
export function X({ size = 14 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
)
}
// ===== 拖拽覆盖层图标 =====
export function UploadCloud({ size = 64 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/>
<polyline points="12 16 12 8"/>
<polyline points="8 12 12 8 16 12"/>
<line x1="12" y1="16" x2="12" y2="22"/>
</svg>
)
}
// ===== 箭头/导航图标 =====
export function ArrowUp({ size = 12 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" y1="19" x2="12" y2="5"/>
<polyline points="5 12 12 5 19 12"/>
</svg>
)
}
export function ArrowDown({ size = 12 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" y1="5" x2="12" y2="19"/>
<polyline points="19 12 12 19 5 12"/>
</svg>
)
}
// ===== 欢迎屏幕图标 =====
export function WelcomeFile({ size = 20 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
<line x1="12" y1="11" x2="12" y2="17"/>
<line x1="9" y1="14" x2="15" y2="14"/>
</svg>
)
}
export function WelcomeNew({ size = 20 }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
<line x1="12" y1="18" x2="12" y2="12"/>
<line x1="9" y1="15" x2="15" y2="15"/>
</svg>
)
}