feat: 主题切换性能优化 — View Transitions API + 0.15s 统一过渡 + 设置页增强
【问题】
桌面端(Electron)切换主题时颜色变化速度不一致、明显卡顿。
根因分析(4 轮迭代):
1. 过渡时长不统一(body 0.3s / 组件 0.15s)→ 统一到 0.2s
2. antd CSS-in-JS 标签替换导致瞬间变色 → 尝试 cssVar(无效,仍走标签替换)
3. applyHtmlTheme 在 updater 回调中执行,与 antd CSS 变更不同帧 → 移入 useLayoutEffect
4. html * 全局过渡在 Electron 中为数千 DOM 节点同步插值 → 合成器掉帧
终极方案:View Transitions API(GPU 合成器 1 次 cross-fade 替代 N 个 CSS 过渡)
+ 精准 CSS 过渡覆盖 ~80 个 antd 容器类(回退方案)
【修改】
ThemeProvider.tsx — 核心重构
- applyHtmlTheme 从 setIsDark updater → useLayoutEffect([isDark])
确保自定义 CSS 变量与 antd CSS-in-JS 在同一次 React 提交中生效
- View Transitions API:document.startViewTransition + flushSync
GPU 合成器截取旧/新两帧做单次 cross-fade,消除多元素插值卡顿
- 浏览器不支持时自动回退到 CSS transition 方案
globals.css — 过渡策略
- body: 0.3s ease → 0.15s linear
- View Transitions 动画:::view-transition-old/new(root) 0.15s linear
- ~80 个 antd 容器类精准过渡(Layout/Card/Modal/Table/Input/
Select/Picker/Menu/Tabs/Tag/Alert/Empty/Result/Skeleton 等)
按功能分组:布局 → 表格 → 表单 → 导航 → 反馈
不覆盖交互组件自有 transition(Button/Switch/Slider 等)
linear 替代 ease — 匀速插值,桌面应用更利落
Layout.tsx / HomeContent.tsx / LeftPanel.tsx / ModelSelector.tsx
- 过渡参数对齐:全部 0.2s → 0.15s linear
SettingsPage.tsx — 用户体验
- Modal 取消 keyboard={false},Esc 键可关闭
- macOS:关闭按钮移至标题左侧(遵循 macOS HIG)
- afterClose 中 blur 当前焦点元素,防止聚焦跳到导航栏
【文档】
CHANGELOG.md — 新增 0.0.15 版本记录
CLAUDE.md — 新增主题系统架构章节(双轨颜色体系 / 时序 / 过渡策略)
This commit is contained in:
@@ -168,8 +168,125 @@ body {
|
||||
background-color: var(--color-bg-base);
|
||||
min-height: 100vh;
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
color 0.3s ease;
|
||||
background-color 0.15s linear,
|
||||
color 0.15s linear;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* View Transitions API — GPU 合成器驱动的主题切换动画
|
||||
* 替代 80+ 个独立 CSS 过渡,单次 cross-fade 消除 Electron 卡顿。
|
||||
* 仅在 Chromium 111+(Electron 28+)生效,其他浏览器回退 CSS 过渡。
|
||||
* ============================================================ */
|
||||
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.15s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 主题切换过渡 — 精准覆盖大面积视觉容器,避免 * 全局选择器
|
||||
* 在 Electron 中为数千个 DOM 节点同时启动过渡造成卡顿。
|
||||
*
|
||||
* 策略:
|
||||
* 1. 容器/布局组件(Card / Modal / Layout / Drawer 等)
|
||||
* 2. 表格 & 列表(Table / List / Timeline)
|
||||
* 3. 表单控件(Input / Select / Picker)
|
||||
* 4. 导航 & 标签(Menu / Tabs / Tag / Breadcrumb)
|
||||
* 5. 反馈 & 展示(Alert / Empty / Result / Statistic / Skeleton)
|
||||
*
|
||||
* 不覆盖交互组件自有 transition(Button / Switch / Slider 等
|
||||
* 均使用 transition: all,特异性更高不受影响)。
|
||||
* ============================================================ */
|
||||
|
||||
/* —— 布局 & 容器 —— */
|
||||
body,
|
||||
.ant-layout,
|
||||
.ant-layout-header,
|
||||
.ant-layout-sider,
|
||||
.ant-layout-content,
|
||||
.ant-card,
|
||||
.ant-card-head,
|
||||
.ant-card-body,
|
||||
.ant-card-actions,
|
||||
.ant-modal-content,
|
||||
.ant-modal-header,
|
||||
.ant-modal-body,
|
||||
.ant-modal-footer,
|
||||
.ant-drawer-content,
|
||||
.ant-drawer-header,
|
||||
.ant-drawer-body,
|
||||
.ant-drawer-footer,
|
||||
|
||||
/* —— 表格 & 列表 —— */
|
||||
.ant-table,
|
||||
.ant-table-thead > tr > th,
|
||||
.ant-table-tbody > tr > td,
|
||||
.ant-table-tbody > tr:hover > td,
|
||||
.ant-list,
|
||||
.ant-list-item,
|
||||
.ant-timeline-item,
|
||||
.ant-transfer-list,
|
||||
.ant-tree-node-content-wrapper,
|
||||
|
||||
/* —— 表单控件 —— */
|
||||
.ant-input,
|
||||
.ant-input-affix-wrapper,
|
||||
.ant-select-selector,
|
||||
.ant-select-dropdown,
|
||||
.ant-picker,
|
||||
.ant-picker-input,
|
||||
.ant-picker-dropdown,
|
||||
.ant-picker-panel-container,
|
||||
.ant-input-number,
|
||||
.ant-input-number-input,
|
||||
.ant-radio-button-wrapper,
|
||||
.ant-radio-group,
|
||||
.ant-checkbox-wrapper,
|
||||
.ant-segmented,
|
||||
.ant-segmented-item,
|
||||
.ant-upload-drag,
|
||||
.ant-upload-list-item,
|
||||
|
||||
/* —— 导航 & 标签 —— */
|
||||
.ant-menu,
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title,
|
||||
.ant-tabs-nav,
|
||||
.ant-tabs-nav-list,
|
||||
.ant-tabs-tab,
|
||||
.ant-tabs-content,
|
||||
.ant-tag,
|
||||
.ant-breadcrumb,
|
||||
.ant-pagination-item,
|
||||
.ant-dropdown-menu,
|
||||
|
||||
/* —— 反馈 & 展示 —— */
|
||||
.ant-alert,
|
||||
.ant-empty,
|
||||
.ant-result,
|
||||
.ant-statistic,
|
||||
.ant-statistic-content,
|
||||
.ant-badge,
|
||||
.ant-avatar,
|
||||
.ant-divider,
|
||||
.ant-skeleton,
|
||||
.ant-skeleton-input,
|
||||
.ant-skeleton-button,
|
||||
.ant-notification-notice,
|
||||
.ant-message-notice-content,
|
||||
.ant-popover-inner,
|
||||
.ant-tooltip-inner,
|
||||
.ant-collapse,
|
||||
.ant-collapse-item,
|
||||
.ant-collapse-header,
|
||||
.ant-collapse-content-box,
|
||||
.ant-descriptions-item-container {
|
||||
transition:
|
||||
color 0.15s linear,
|
||||
background-color 0.15s linear,
|
||||
border-color 0.15s linear,
|
||||
box-shadow 0.15s linear;
|
||||
}
|
||||
|
||||
#root {
|
||||
|
||||
Reference in New Issue
Block a user