From 8e368948516159a0a9894fb54d066c7fb6ce16c5 Mon Sep 17 00:00:00 2001 From: TerryM Date: Fri, 29 May 2026 10:44:54 +0800 Subject: [PATCH] docs: add website motion & UX design spec --- .../2026-05-29-website-motion-ux-design.md | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-29-website-motion-ux-design.md diff --git a/docs/superpowers/specs/2026-05-29-website-motion-ux-design.md b/docs/superpowers/specs/2026-05-29-website-motion-ux-design.md new file mode 100644 index 0000000..53288d8 --- /dev/null +++ b/docs/superpowers/specs/2026-05-29-website-motion-ux-design.md @@ -0,0 +1,103 @@ +# 网站动画与 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` 的 `` 外层用 `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。