frontend: FE-026 现代桌面风设计基建,系统字体栈+中性灰分层+蓝色主色+圆角阴影动效令牌
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+74
-53
@@ -1,13 +1,18 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "tw-animate-css";
|
@import "tw-animate-css";
|
||||||
@import "shadcn/tailwind.css";
|
@import "shadcn/tailwind.css";
|
||||||
@import "@fontsource-variable/roboto-slab";
|
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 现代桌面工具风设计基建(FE-026)
|
||||||
|
* 基调:中性灰分层底色 + 卡片化 + 克制的蓝色主色,参照 Codex 桌面端 / CC Switch。
|
||||||
|
* 动效约定:快 150ms / 标准 200ms / 慢 250ms,对应 duration-150 / duration-200 / duration-250。
|
||||||
|
*/
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--font-heading: var(--font-serif);
|
--font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||||||
--font-serif: 'Roboto Slab Variable', serif;
|
--font-heading: var(--font-sans);
|
||||||
|
--font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
--color-sidebar-border: var(--sidebar-border);
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
@@ -39,6 +44,7 @@
|
|||||||
--color-card: var(--card);
|
--color-card: var(--card);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
|
/* 圆角档位:sm 6px / md 8px / lg 10px / xl 14px(--radius = 10px) */
|
||||||
--radius-sm: calc(var(--radius) * 0.6);
|
--radius-sm: calc(var(--radius) * 0.6);
|
||||||
--radius-md: calc(var(--radius) * 0.8);
|
--radius-md: calc(var(--radius) * 0.8);
|
||||||
--radius-lg: var(--radius);
|
--radius-lg: var(--radius);
|
||||||
@@ -46,75 +52,90 @@
|
|||||||
--radius-2xl: calc(var(--radius) * 1.8);
|
--radius-2xl: calc(var(--radius) * 1.8);
|
||||||
--radius-3xl: calc(var(--radius) * 2.2);
|
--radius-3xl: calc(var(--radius) * 2.2);
|
||||||
--radius-4xl: calc(var(--radius) * 2.6);
|
--radius-4xl: calc(var(--radius) * 2.6);
|
||||||
|
/* 阴影分层:卡片极轻 / 浮层轻 / 弹窗明显 */
|
||||||
|
--shadow-card: 0 1px 2px rgb(0 0 0 / 0.04);
|
||||||
|
--shadow-overlay: 0 4px 16px rgb(0 0 0 / 0.08), 0 1px 3px rgb(0 0 0 / 0.06);
|
||||||
|
--shadow-dialog: 0 16px 48px rgb(0 0 0 / 0.16), 0 4px 12px rgb(0 0 0 / 0.08);
|
||||||
|
/* 缓动曲线:出场用 out-quart,强调动效用 spring 近似 */
|
||||||
|
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
|
||||||
|
--ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: oklch(1 0 0);
|
/* 中性灰分层:页面底 0.985 / 卡片 1 / 侧栏 0.967 / 悬停 0.945 */
|
||||||
--foreground: oklch(0.145 0 0);
|
--background: oklch(0.985 0.002 286);
|
||||||
|
--foreground: oklch(0.21 0.006 286);
|
||||||
--card: oklch(1 0 0);
|
--card: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.145 0 0);
|
--card-foreground: oklch(0.21 0.006 286);
|
||||||
--popover: oklch(1 0 0);
|
--popover: oklch(1 0 0);
|
||||||
--popover-foreground: oklch(0.145 0 0);
|
--popover-foreground: oklch(0.21 0.006 286);
|
||||||
--primary: oklch(0.488 0.243 264.376);
|
/* 克制的蓝色主色:仅用于主按钮、选中态、状态点 */
|
||||||
--primary-foreground: oklch(0.97 0.014 254.604);
|
--primary: oklch(0.546 0.215 262.881);
|
||||||
--secondary: oklch(0.967 0.001 286.375);
|
--primary-foreground: oklch(0.985 0.002 286);
|
||||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
--secondary: oklch(0.96 0.004 286);
|
||||||
--muted: oklch(0.97 0 0);
|
--secondary-foreground: oklch(0.21 0.006 286);
|
||||||
--muted-foreground: oklch(0.556 0 0);
|
--muted: oklch(0.96 0.004 286);
|
||||||
--accent: oklch(0.488 0.243 264.376);
|
--muted-foreground: oklch(0.552 0.014 285);
|
||||||
--accent-foreground: oklch(0.97 0.014 254.604);
|
/* accent 为中性悬停底色,不再复用主色 */
|
||||||
|
--accent: oklch(0.945 0.004 286);
|
||||||
|
--accent-foreground: oklch(0.21 0.006 286);
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
--border: oklch(0.922 0 0);
|
--border: oklch(0.92 0.004 286);
|
||||||
--input: oklch(0.922 0 0);
|
--input: oklch(0.92 0.004 286);
|
||||||
--ring: oklch(0.708 0 0);
|
--ring: oklch(0.623 0.188 259.815);
|
||||||
--chart-1: oklch(0.809 0.105 251.813);
|
--chart-1: oklch(0.809 0.105 251.813);
|
||||||
--chart-2: oklch(0.623 0.214 259.815);
|
--chart-2: oklch(0.623 0.214 259.815);
|
||||||
--chart-3: oklch(0.546 0.245 262.881);
|
--chart-3: oklch(0.546 0.245 262.881);
|
||||||
--chart-4: oklch(0.488 0.243 264.376);
|
--chart-4: oklch(0.488 0.243 264.376);
|
||||||
--chart-5: oklch(0.424 0.199 265.638);
|
--chart-5: oklch(0.424 0.199 265.638);
|
||||||
--radius: 0.875rem;
|
--radius: 0.625rem;
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.967 0.003 286);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0.21 0.006 286);
|
||||||
--sidebar-primary: oklch(0.546 0.245 262.881);
|
--sidebar-primary: oklch(0.546 0.215 262.881);
|
||||||
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
|
--sidebar-primary-foreground: oklch(0.985 0.002 286);
|
||||||
--sidebar-accent: oklch(0.97 0 0);
|
--sidebar-accent: oklch(0.92 0.004 286);
|
||||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
--sidebar-accent-foreground: oklch(0.21 0.006 286);
|
||||||
--sidebar-border: oklch(0.922 0 0);
|
--sidebar-border: oklch(0.91 0.004 286);
|
||||||
--sidebar-ring: oklch(0.708 0 0);
|
--sidebar-ring: oklch(0.623 0.188 259.815);
|
||||||
|
/* 动效时长:快 / 标准 / 慢 */
|
||||||
|
--motion-fast: 150ms;
|
||||||
|
--motion-base: 200ms;
|
||||||
|
--motion-slow: 250ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.145 0 0);
|
/* 深灰底而非纯黑:页面 0.185 / 卡片 0.22 / 侧栏 0.165 / 悬停 0.27 */
|
||||||
--foreground: oklch(0.985 0 0);
|
--background: oklch(0.185 0.005 285);
|
||||||
--card: oklch(0.205 0 0);
|
--foreground: oklch(0.96 0.002 286);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card: oklch(0.22 0.006 285);
|
||||||
--popover: oklch(0.205 0 0);
|
--card-foreground: oklch(0.96 0.002 286);
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
--popover: oklch(0.22 0.006 285);
|
||||||
--primary: oklch(0.424 0.199 265.638);
|
--popover-foreground: oklch(0.96 0.002 286);
|
||||||
--primary-foreground: oklch(0.97 0.014 254.604);
|
--primary: oklch(0.623 0.188 259.815);
|
||||||
--secondary: oklch(0.274 0.006 286.033);
|
--primary-foreground: oklch(0.985 0.002 286);
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
--secondary: oklch(0.27 0.006 286);
|
||||||
--muted: oklch(0.269 0 0);
|
--secondary-foreground: oklch(0.96 0.002 286);
|
||||||
--muted-foreground: oklch(0.708 0 0);
|
--muted: oklch(0.26 0.006 286);
|
||||||
--accent: oklch(0.424 0.199 265.638);
|
--muted-foreground: oklch(0.71 0.01 286);
|
||||||
--accent-foreground: oklch(0.97 0.014 254.604);
|
--accent: oklch(0.27 0.006 286);
|
||||||
|
--accent-foreground: oklch(0.96 0.002 286);
|
||||||
--destructive: oklch(0.704 0.191 22.216);
|
--destructive: oklch(0.704 0.191 22.216);
|
||||||
--border: oklch(1 0 0 / 10%);
|
--border: oklch(1 0 0 / 8%);
|
||||||
--input: oklch(1 0 0 / 15%);
|
--input: oklch(1 0 0 / 12%);
|
||||||
--ring: oklch(0.556 0 0);
|
--ring: oklch(0.623 0.188 259.815);
|
||||||
--chart-1: oklch(0.809 0.105 251.813);
|
--chart-1: oklch(0.809 0.105 251.813);
|
||||||
--chart-2: oklch(0.623 0.214 259.815);
|
--chart-2: oklch(0.623 0.214 259.815);
|
||||||
--chart-3: oklch(0.546 0.245 262.881);
|
--chart-3: oklch(0.546 0.245 262.881);
|
||||||
--chart-4: oklch(0.488 0.243 264.376);
|
--chart-4: oklch(0.488 0.243 264.376);
|
||||||
--chart-5: oklch(0.424 0.199 265.638);
|
--chart-5: oklch(0.424 0.199 265.638);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--sidebar: oklch(0.165 0.005 285);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.96 0.002 286);
|
||||||
--sidebar-primary: oklch(0.623 0.214 259.815);
|
--sidebar-primary: oklch(0.623 0.188 259.815);
|
||||||
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
|
--sidebar-primary-foreground: oklch(0.985 0.002 286);
|
||||||
--sidebar-accent: oklch(0.269 0 0);
|
--sidebar-accent: oklch(0.24 0.006 285);
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-accent-foreground: oklch(0.96 0.002 286);
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
--sidebar-border: oklch(1 0 0 / 8%);
|
||||||
--sidebar-ring: oklch(0.556 0 0);
|
--sidebar-ring: oklch(0.623 0.188 259.815);
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
@@ -125,6 +146,6 @@
|
|||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
html {
|
html {
|
||||||
@apply font-serif;
|
@apply font-sans;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
"format": "prettier --write \"**/*.{ts,tsx}\""
|
"format": "prettier --write \"**/*.{ts,tsx}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/roboto-slab": "^5.2.8",
|
|
||||||
"@react-router/node": "7.13.1",
|
"@react-router/node": "7.13.1",
|
||||||
"@react-router/serve": "7.13.1",
|
"@react-router/serve": "7.13.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
|||||||
Generated
-8
@@ -8,9 +8,6 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fontsource-variable/roboto-slab':
|
|
||||||
specifier: ^5.2.8
|
|
||||||
version: 5.2.8
|
|
||||||
'@react-router/node':
|
'@react-router/node':
|
||||||
specifier: 7.13.1
|
specifier: 7.13.1
|
||||||
version: 7.13.1(react-router@7.13.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
|
version: 7.13.1(react-router@7.13.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@5.9.3)
|
||||||
@@ -416,9 +413,6 @@ packages:
|
|||||||
'@floating-ui/utils@0.2.11':
|
'@floating-ui/utils@0.2.11':
|
||||||
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
|
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
|
||||||
|
|
||||||
'@fontsource-variable/roboto-slab@5.2.8':
|
|
||||||
resolution: {integrity: sha512-cdvOSwocP50xS01gXqnGxw7uFcCZQgn1IDlqiAmNuZP4uEVScYAKMDC+aWsbP1grn9QdMJ2frhcuVBNXniBVGA==}
|
|
||||||
|
|
||||||
'@hapi/address@5.1.1':
|
'@hapi/address@5.1.1':
|
||||||
resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==}
|
resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -3742,8 +3736,6 @@ snapshots:
|
|||||||
|
|
||||||
'@floating-ui/utils@0.2.11': {}
|
'@floating-ui/utils@0.2.11': {}
|
||||||
|
|
||||||
'@fontsource-variable/roboto-slab@5.2.8': {}
|
|
||||||
|
|
||||||
'@hapi/address@5.1.1':
|
'@hapi/address@5.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hapi/hoek': 11.0.7
|
'@hapi/hoek': 11.0.7
|
||||||
|
|||||||
+4
-4
@@ -31,10 +31,10 @@ blocked
|
|||||||
| Core | 12 | 12 | 100% |
|
| Core | 12 | 12 | 100% |
|
||||||
| Server API | 10 | 10 | 100% |
|
| Server API | 10 | 10 | 100% |
|
||||||
| CLI | 2 | 2 | 100% |
|
| CLI | 2 | 2 | 100% |
|
||||||
| Frontend | 25 | 34 | 74% |
|
| Frontend | 26 | 34 | 76% |
|
||||||
| Feature E2E | 0 | 5 | 0% |
|
| Feature E2E | 0 | 5 | 0% |
|
||||||
| Release | 0 | 4 | 0% |
|
| Release | 0 | 4 | 0% |
|
||||||
| Overall | 49 | 67 | 73% |
|
| Overall | 50 | 67 | 75% |
|
||||||
|
|
||||||
## 当前阶段
|
## 当前阶段
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ UI 风格改版(分支 `feature/ui-modern-restyle`,FE-026 ~ FE-034,需求
|
|||||||
|
|
||||||
## 下一步任务
|
## 下一步任务
|
||||||
|
|
||||||
- [FE-026-建立现代桌面风设计基建.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-026-建立现代桌面风设计基建.md)
|
- [FE-027-Electron无缝窗口与自绘顶栏.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-027-Electron无缝窗口与自绘顶栏.md)
|
||||||
- UI 改版完成后再回到 [FEATURE-001-连接与目录浏览端到端验收.md](/Users/fenghp/Desktop/DEV/project/mydev/task/feature/FEATURE-001-连接与目录浏览端到端验收.md)(需要真实 TFS 环境)
|
- UI 改版完成后再回到 [FEATURE-001-连接与目录浏览端到端验收.md](/Users/fenghp/Desktop/DEV/project/mydev/task/feature/FEATURE-001-连接与目录浏览端到端验收.md)(需要真实 TFS 环境)
|
||||||
|
|
||||||
## Core
|
## Core
|
||||||
@@ -117,7 +117,7 @@ UI 风格改版(分支 `feature/ui-modern-restyle`,FE-026 ~ FE-034,需求
|
|||||||
| [FE-023-实现分支.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-023-实现分支.md) | done | P1 |
|
| [FE-023-实现分支.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-023-实现分支.md) | done | P1 |
|
||||||
| [FE-024-实现合并.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-024-实现合并.md) | done | P1 |
|
| [FE-024-实现合并.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-024-实现合并.md) | done | P1 |
|
||||||
| [FE-025-实现访达打开与添加本地文件.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-025-实现访达打开与添加本地文件.md) | done | P0 |
|
| [FE-025-实现访达打开与添加本地文件.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-025-实现访达打开与添加本地文件.md) | done | P0 |
|
||||||
| [FE-026-建立现代桌面风设计基建.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-026-建立现代桌面风设计基建.md) | todo | P0 |
|
| [FE-026-建立现代桌面风设计基建.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-026-建立现代桌面风设计基建.md) | done | P0 |
|
||||||
| [FE-027-Electron无缝窗口与自绘顶栏.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-027-Electron无缝窗口与自绘顶栏.md) | todo | P0 |
|
| [FE-027-Electron无缝窗口与自绘顶栏.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-027-Electron无缝窗口与自绘顶栏.md) | todo | P0 |
|
||||||
| [FE-028-重设计登录页.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-028-重设计登录页.md) | todo | P0 |
|
| [FE-028-重设计登录页.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-028-重设计登录页.md) | todo | P0 |
|
||||||
| [FE-029-工作台外壳与顶栏改版.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-029-工作台外壳与顶栏改版.md) | todo | P0 |
|
| [FE-029-工作台外壳与顶栏改版.md](/Users/fenghp/Desktop/DEV/project/mydev/task/frontend/FE-029-工作台外壳与顶栏改版.md) | todo | P0 |
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 状态
|
## 状态
|
||||||
|
|
||||||
todo
|
done
|
||||||
|
|
||||||
## 优先级
|
## 优先级
|
||||||
|
|
||||||
@@ -58,9 +58,19 @@ cd mactfsui && pnpm typecheck && pnpm electron:dev
|
|||||||
|
|
||||||
## 完成记录
|
## 完成记录
|
||||||
|
|
||||||
待完成后填写:
|
|
||||||
|
|
||||||
- 实际修改文件:
|
- 实际修改文件:
|
||||||
|
- `mactfsui/app/app.css`
|
||||||
|
- `mactfsui/package.json`、`mactfsui/pnpm-lock.yaml`(移除 `@fontsource-variable/roboto-slab`)
|
||||||
- 实际实现内容:
|
- 实际实现内容:
|
||||||
|
- 全局字体切换为系统无衬线字体栈(`-apple-system / PingFang SC`…),`html` 由 `font-serif` 改为 `font-sans`;新增 `--font-mono` 等宽字体令牌;`--font-heading` 指向 sans(dialog 标题沿用)
|
||||||
|
- 颜色令牌重定义为中性灰分层:light 页面底 0.985 / 卡片纯白 / 侧栏 0.967 / 悬停 0.945;dark 深灰底 0.185(非纯黑)/ 卡片 0.22 / 侧栏 0.165
|
||||||
|
- 主色改为克制的蓝色(oklch 0.546 0.215 262.881),`--accent` 与主色解耦、改为中性悬停底色(原先 accent=紫色主色,菜单悬停会大面积铺色)
|
||||||
|
- 圆角基准 0.875rem → 0.625rem(sm 6 / md 8 / lg 10 / xl 14px)
|
||||||
|
- 新增阴影分层令牌 `--shadow-card / --shadow-overlay / --shadow-dialog`
|
||||||
|
- 新增动效令牌:缓动 `--ease-out-quart / --ease-spring`,时长 `--motion-fast/base/slow`(150/200/250ms)
|
||||||
- 测试结果:
|
- 测试结果:
|
||||||
|
- `pnpm typecheck` 通过
|
||||||
|
- `pnpm build` 通过(Tailwind CSS 编译无误)
|
||||||
|
- 未执行 `pnpm electron:dev` 全页面人工走查(属 GUI 交互验证,留待后续任务连带走查),现有类名均基于既有 token 体系,无破坏性重命名
|
||||||
- 遗留问题:
|
- 遗留问题:
|
||||||
|
- 各组件中残留的散落样式(如紫色 hover 假设)将在 FE-029 ~ FE-032 按面板逐一对齐
|
||||||
|
|||||||
Reference in New Issue
Block a user