Files
Arkie-Library-Frontend/docs/superpowers/specs/2026-05-29-website-motion-ux-design.md
2026-05-29 10:44:54 +08:00

104 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 网站动画与 UX 提升 — 设计文件
**日期**: 2026-05-29
**目标**: 在**不改变 UI 布局和颜色**的前提下,为 Arkie Library 前端加入精致动画并提升使用者体验,效果与性能兼顾,并顺手清理冗余代码。
---
## 1. 背景与约束
- 技术栈React 18 + TypeScript + Vite + Tailwind CSS。
- 主题:深色 (`#141319`),金色重点 (`#eeb726` / `#ffd35c`)。
- 现有动画:`ark-page-fade-in`(页面淡入 240ms`ark-header-menu-enter`(菜单 clip-path 180ms皆已支援 `prefers-reduced-motion`
- **硬约束**
- 不改变任何布局、颜色、字体、间距。仅加入「动作 / 时间 / 反馈」。
- 全部动画必须尊重 `prefers-reduced-motion: reduce`
- 效果与性能兼顾库需按需加载、bundle 影响最小化。
## 2. 决策(已与用户确认)
| 项目 | 决定 |
|------|------|
| 动画强度 | 适中活泼moderate & lively克制但明显 |
| 范围 | 全站(首页、浏览、分类、分类详情、搜索、关于、收藏) |
| 实现方式 | **混合方案**`framer-motion`LazyMotion 精简模式)+ 纯 CSS/Tailwind |
| 冗余清理 | 实作中一并清理(如 `RecommendedCard` 内两边相同的三元运算) |
### 库分工
- **framer-motion (v11, `LazyMotion` + `m`)**:页面切换退场动画(`AnimatePresence`)、弹簧悬停质感、筛选/排序卡片重排(`layout`)、复杂 stagger 编排。
- **CSS / Tailwind**:骨架屏 shimmer、图片加载淡入、简单滚动出现无需 framer 的场景)。
## 3. 架构与组件
### 3.1 动画基础设施(一次建好,全站复用)
- `tailwind.config.js`:新增 `keyframes``shimmer``fade-in-up``scale-in`)、对应 `animation`,统一缓动 `cubic-bezier(0.22, 1, 0.36, 1)`
- `src/index.css`:新增可复用工具类与 reduced-motion 保护。
- `src/motion/` 新目录:
- `MotionProvider.tsx`:包 `LazyMotion``domAnimation` features全站只引入一次确保精简 bundle。
- `variants.ts`:共享 variants`fadeInUp``staggerContainer``cardHover``pageTransition`)与统一 transition 设定。
- `useRevealOnScroll.ts`:轻量 `IntersectionObserver` hook元素进入视窗触发一次CSS 路径用)。
- `Reveal.tsx`:薄包装组件,子元素滚动进入视窗时 fade-in-up内部用 framer 的 `whileInView` 或 CSS hook择一统一
### 3.2 页面切换退场framer-motion
-`PublicLayout``<Outlet/>` 外层用 `AnimatePresence mode="wait"`,以 `pathname+search` 为 key。
- 退场/进场使用 `pageTransition` variant淡入 + 轻微位移,~220ms
- 取代现有 `ark-page-fade-in`(避免重复;保留 CSS 作为 reduced-motion fallback
### 3.3 滚动出现Scroll Reveal
- 列表/区块(首页 carousel/区段、浏览 grid、分类卡片`Reveal` 包装,依序 stagger~60ms淡入上浮只触发一次。
- grid 大量项目时限制 stagger 上限,避免长列表整体延迟。
### 3.4 悬停与微互动(不改样式,仅加动作)
- 卡片:现有 `hover:scale-[1.02]` 升级为 framer 弹簧整卡轻浮 + 阴影过渡(沿用金色边框)。
- 下载按钮:`active:scale` 点击反馈 + 完成时的状态过渡。
- 导航连结:金色下划线滑入(`gold-underline` 过渡化)。
### 3.5 载入与反馈UX 重点)
- **骨架屏**:新增 `src/components/Skeleton.tsx`(带 shimmer用于列表/卡片/详情加载态,取代空白或突兀闪现。
- **图片淡入**:图片 `onLoad` 后淡入(卡片封面、详情图),避免硬切。
- **Toast**:轻量 `src/components/Toast.tsx` + provider下载成功/失败提示(沿用现有配色),无障碍 `aria-live`
## 4. 冗余代码清理
- `RecommendedCard.tsx`
- `useFigmaDesign ? "group-hover:scale-[1.02]" : "group-hover:scale-[1.02]"` → 两边相同,简化。
- spinner `useFigmaDesign ? "h-5 w-5 animate-spin" : "h-5 w-5 animate-spin"` → 简化。
- 实作各档案时移除遇到的同类重复(不做无关重构)。
## 5. 资料流 / 隔离
- 动画相关逻辑集中于 `src/motion/`,组件只引用 variants/hook不内嵌魔术数字。
- `MotionProvider` 在 app root 包一次;各页面无需重复设定。
- 骨架屏 / Toast 为独立、可单测的展示组件。
## 6. 无障碍与性能
- 所有 framer 动画与 CSS 动画在 `prefers-reduced-motion: reduce` 下降级为无动作或纯淡入。
- 使用 `LazyMotion` 精简 features避免引入完整 framer bundle。
- 动画用 `transform`/`opacity`GPU 友好),避免 layout thrash。
- build 后检查 bundle 体积变化在可接受范围。
## 7. 实作顺序
1. 安装 framer-motion + 建 `src/motion/` 基础设施 + tailwind/CSS keyframes。
2. `MotionProvider` 接入 app root。
3. 页面切换退场PublicLayout
4. Scroll reveal全站列表/区块)。
5. 骨架屏 + 图片淡入。
6. 悬停/微互动升级。
7. Toast 反馈。
8. 清理冗余代码。
9. `npm run build` 验证 + reduced-motion 验证。
## 8. 验收标准
- 视觉布局/颜色与改动前一致(仅多了动作)。
- `npm run build` 通过bundle 增量可控framer 精简模式)。
- 开启「减少动态效果」时网站仍可正常使用、无动画。
- 全站列表有 scroll reveal、卡片有弹簧悬停、加载有骨架屏、下载有 toast。