Files
EPEEAIKit/docs/art-agent/UX-STYLE-GUIDE.md

17 KiB
Raw Blame History

EPEEKit 交互体验指南

设计语言:青绿山水 · 科技幽谷 核心意境:深山幽谷中的科技圣地 — 自然的宁静与数字的精密共存 更新日期2026-04-16

实现状态说明

每个特性标注实现状态:

  • 已实现 — 代码完整落地,与文档描述一致
  • 🔶 基本实现 — 核心功能已落地,细节有微小偏差(不影响体验)
  • 未实现 — 仅有文档描述,无对应代码

1. 设计哲学

每一次交互都是一次"与山水对话"

操作 意象 动效语言 状态
发送消息 投石入水 按钮弹缩 → 气泡飞入 → 涟漪扩散
AI 回复 云雾凝聚 模糊→清晰 → 文字逐行显现
收藏图片 萤火点亮 星标亮起 → 金色粒子飘散
滚动浏览 穿行雾中 内容在雾气边缘隐现
等待加载 溪水潺潺 石青流光 + 水波纹脉冲
图片揭示 水墨晕染 clip-path 圆形从中心扩展
会话切换 翻山越岭 内容滑出/滑入

科技感不通过赛博朋克的锐利线条传递,而是通过"精密点阵 × 自然粒子"的融合 — 就像在深山中发现了一座用水晶和苔藓构建的数据中心。


2. 色彩体系

主色调

语义 变量名 色值 色彩隐喻 状态
背景主色 --bg-primary #0C1210 深山暗处
背景次级 --bg-secondary #131E1A 苔藓暗绿 / 山石基底
背景三级 --bg-tertiary #1C2A24 松烟绿 / 远山中层
卡片表面 --bg-card rgba(16, 30, 24, 0.65) 半透明山岩
主高亮色 --accent #4DB8A4 石青绿 — 千里江山图的石青
高亮 hover --accent-hover #6CD4BE 石青亮态
辅助高亮 --accent-secondary #3A8FB7 石绿蓝 — 千里江山图的石绿
热门/警告 --hot #C4654A 赭石红 — 点景人物/宫殿暖色
文字主色 --text-primary #E0E8E2 微泛绿的月白
文字次级 --text-secondary #7A9485 青灰绿
边框色 --border rgba(77, 184, 164, 0.12) 石青半透明
发光边框 --border-glow rgba(77, 184, 164, 0.25) 石青发光态
雾气基础 --mist rgba(77, 184, 164, 0.06) 云雾底色
赭金点缀 --gold #B8935A 收藏星标等极少量暖色

色彩来源

石青(#4DB8A4)和石绿蓝(#3A8FB7)取自《千里江山图》中使用的矿物质颜料色, 经现代演绎降低饱和度,在深色 UI 中不过于刺眼。 赭石红(#C4654A)来源于画中点景人物和宫殿使用的暖色颜料。

实现文件: globals.css :root 第 4-18 行


3. 信息层级体系

3.1 排版重量体系7 级)

层级 CSS 类 大小 字重 字间距 视觉手段 状态
Display .typo-display 32px 300 -0.02em 石青→石绿蓝渐变填色
H1 .typo-h1 24px 700 -0.01em 底部石青细线装饰
H2 .typo-h2 18px 600 0 左侧 3px 石青竖线标记
Body 默认 14px 400 0.01em 标准
Body Strong .typo-strong 14px 600 0 石青色
Caption .typo-caption 12px 400 0.02em text-secondary
Micro .typo-micro 11px 600 0.04em 大写 + 加宽字间距

关键区分手段Display 使用渐变文字而非纯色H1 与 H2 各有独立视觉标记(底线 vs 竖线), 不仅靠字号大小区分层级。

实现文件: globals.css 第 33-102 行 使用位置: typo-display(欢迎页/登录页)、typo-h1ProfileModal 用户名)、typo-h2Gallery 详情标题)、typo-strong(侧栏/Gallery 区域标题、ProfileModal 记忆标题)、typo-caption(时间戳/记忆条数)、typo-micro(标签/分组标签/New 标记)

3.2 表面层级系统Surface Elevation

4 级表面,每升一级 backdrop-blur +8px、border 亮度 +0.06、box-shadow 扩展 +4px

层级 CSS 类 用途 隐喻 状态
Surface-0 页面背景 #0C1210 深渊
Surface-1 .surface-1 侧栏/主区域 山脚bg-secondary + 微弱内发光)
Surface-2 .surface-2 卡片/消息气泡 山腰glass-panel + 更强模糊 + 微上移阴影)
Surface-3 .surface-3 弹窗/下拉/tooltip 山顶(强模糊 + 明显阴影 + 更亮边框)

实现文件: globals.css 第 106-133 行 使用位置: 侧栏surface-1、消息气泡/回到底部按钮surface-2、下拉菜单/弹窗surface-3

注:文档定义的 .glass-panel.surface-2 视觉上等价,实际组件统一使用 surface-* 系列。glass-panel 保留为兼容。

3.3 用户消息 vs 助手消息

维度 用户消息 助手消息 状态
对齐 右对齐 左对齐
背景 石青渐变accent/8 → accent/15 glass-panelSurface-2
圆角 左上方切角(几何感) 标准圆角
边框 左侧 2px 石青竖线(山泉流水)
入场动画 投石入水(从下方飞入) 云雾凝聚blur 消散)

实现文件: chat-messages.tsx 第 69-74 行、globals.css .user-bubble


4. 科技质感

4.1 环境粒子Ambient Particles

背景云雾之上叠加"深山萤火"粒子层:

  • 数量15-20 个小光点
  • 颜色石青色opacity 0.15-0.3
  • 行为:缓慢随机漂浮 + 偶尔闪烁opacity 脉冲)
  • 实现React 组件 + useMemo 随机化 + CSS animation
  • 空态时粒子增多至 ~28 个,营造"未探索的深山"感

实现文件: components/ui/ambient-particles.tsx 接入位置: page.tsx首页count 根据空态切换)、login/page.tsxgallery/page.tsx

4.2 网格底纹Subtle Grid

Surface-0 背景叠加极淡的点阵网格opacity: 0.03 几乎不可见但传递"精密、数字化"的潜意识感知,与云雾层形成"自然 × 科技"张力。

实现文件: globals.css body::before 第 136-145 行

4.3 数据流光Data Stream

AI 思考/生成时,输入栏上方出现一条横向流光:

  • 石青色光带从左向右流动,高度 2px
  • 思考时慢速、生成图片时加速
  • 意象:山间溪流 / 数据脉搏

实现文件: components/ui/data-stream.tsxglobals.css .data-stream / -slow / -fast 接入位置: chat-input.tsx 第 202 行


5. 微交互图鉴

所有微交互使用 framer-motion 实现,统一动画参数定义在 motion-presets.ts 中。

5.1 发送消息 — "投石入水"

  1. 发送按钮 scale(0.85) → spring 弹回(sendBounce
  2. 消息气泡从输入栏位置飞入对话区translateY + opacity
  3. 到达目标位置时涟漪扩散(RippleLayer 石青色圆环 scale + fade out
  4. 输入栏清空后边框发光脉冲一次(水面恢复平静)

实现文件: chat-input.tsxsendBounce + useRippleripple-effect.tsxmotion-presets.ts

5.2 AI 回复 — "云雾凝聚"

  1. 消息气泡 blur(8px)blur(0) 凝聚显现
  2. 文字逐行显示时 opacity 阶梯(新行更亮,旧行渐稳)
  3. 图片结果:石青色模糊占位 → blur 消散 + scale 1.02→1.0(拨开云雾)

实现文件: motion-presets.ts assistantEnterchat-messages.tsx StreamingLines 组件

5.3 收藏图片 — "萤火点亮"

  1. 星标 outline → filled赭金色
  2. 点击瞬间散出 5-7 个微小金色粒子(萤火被惊起)
  3. 粒子向四周飘散并淡出stagger + random 偏移)

实现文件: components/ui/firefly-burst.tsximage-grid.tsx FavoriteButton

5.4 图片加载 — "水墨晕染"

  1. 占位:石青渐变块 + 呼吸脉冲(.stone-placeholder
  2. 加载完成:clip-path: circle() 从中心扩展到全图(水墨滴入纸面)

实现文件: globals.css .stone-placeholdermotion-presets.ts inkRevealimage-grid.tsx ImageReveal

5.5 输入框 — "水面感应"

  • 空态:底部淡石青线
  • 获焦:边框从中心向两端扩展点亮(水面波纹展开)
  • 输入时:边框亮度随文字长度微增(蓄力)
  • 可发送态:发送按钮缓慢脉冲发光(准备就绪)

实现文件: globals.css .water-focus-line / .water-focus-activechat-input.tsx boxShadow 联动

5.6 Hover 状态

  • 按钮:translateY(-1px) + shadow 加深(浮起感)
  • 卡片border-glow + 底部向上内发光渐变
  • 侧栏会话项:左侧 2px 石青竖线 slide-in

实现文件: globals.css .btn-hover-lift(第 466-472 行)、.neon-border(第 195-204 行)、.session-hover-line(第 474-493 行)

5.7 滚动到底部 — "落叶归根"

  • 形状:水滴形(椭圆切割 border-radius
  • 出现spring 从下方弹入
  • 石青半透明背景 + 雾气边框

实现文件: page.tsx scroll-btn、motion-presets.ts scrollBtnEnter

5.8 会话切换 — "翻山越岭"

  • 当前对话向上/向下滑出
  • 新对话从对应方向滑入
  • 过渡 250ms ease-out
  • 使用 AnimatePresence mode="wait" + sessionSlide 变体

实现文件: page.tsx AnimatePresence 包裹聊天内容区、motion-presets.ts sessionSlide


6. 状态与反馈

6.1 Loading 体系

场景 表现 状态
骨架屏 shimmer 渐变bg-tertiary → bg-secondary左→右扫描
内联加载 三个石青圆点"水波纹"式依次涌起scale Y 变化)
全屏加载 中心放射状云雾凝聚(涟漪环 + 核心光点 + 呼吸脉冲)
AI 生成中 数据流光(输入栏上方 2px 流动光带)

实现文件: globals.css .skeleton-shimmer.wave-dot.mist-loader.data-stream 接入位置: image-grid.tsxchat-messages.tsxapp-context.tsxchat-input.tsx

6.2 空态设计

  • Display 级渐变文字欢迎语
  • "快速开始"建议卡片stagger 入场)
  • 萤火粒子增多营造氛围

实现文件: page.tsx isEmptyState 分支

6.3 Error 状态

  • 赭石红色调但保持优雅(非大红色块)
  • 微弱横向震动translateX ±2px2 次)
  • 自动消失时向上飘散淡出(errorFloat 变体 + 4s 定时清除)

实现文件: globals.css .error-shakemotion-presets.ts errorFloatlogin/page.tsx


7. 动效语言

7.1 时序原则

类别 时长 缓动
即时反馈hover/press 150-200ms ease
状态过渡(展开/折叠) 250ms ease-in-out
云烟效果(淡入/淡出) 400-600ms ease
环境动效(背景漂移) 45-60s ease-in-out infinite
Spring 物理(弹缩) stiffness: 400, damping: 25 spring

7.2 编排原则

  • 先快后慢:触发瞬间最快,收尾最慢(模拟自然物理)
  • 层次递进:多元素入场使用 stagger50-80ms 间隔),从近到远
  • 克制优先微交互幅度小1-3px 位移、0.95-1.05 缩放),避免分散注意力
  • 自然衰减:所有粒子效果都应以 opacity → 0 结束,不突兀消失

7.3 统一动画参数motion-presets.ts

// Spring 物理参数
spring: { stiffness: 400, damping: 25 }
springGentle: { stiffness: 200, damping: 20 }

// 入场动画
fadeIn: { opacity: [0, 1], transition: { duration: 0.2 } }
slideUp: { opacity: [0, 1], y: [8, 0], transition: { duration: 0.2 } }
mistReveal: { filter: ["blur(8px)", "blur(0px)"], opacity: [0, 1], duration: 0.4 }

// 按钮反馈
buttonTap: { scale: 0.85 }
sendBounce: { scale: [1, 0.85, 1.05, 1], transition: { duration: 0.3 } }

// 涟漪/粒子
ripple: { scale: [0, 2.5], opacity: [0.4, 0], duration: 0.6 }
sparkle: { scale: [0, 1, 0], opacity: [0, 1, 0], duration: 0.8 }

// 会话切换
sessionSlide: { enter  center  exit, y ±30, duration: 0.25 }

// Error 飘散
errorFloat: { exit  opacity: 0, y: -12, duration: 0.5 }

实现文件: components/ui/motion-presets.ts


8. 视觉效果

8.1 山雾玻璃面板

.glass-panel {
  background:
    linear-gradient(165deg, rgba(16, 30, 24, 0.15) 0%, transparent 50%),
    rgba(16, 30, 24, 0.55);
  backdrop-filter: blur(24px) saturate(1.1);
  border: 1px solid var(--border);
}

实现文件: globals.css 第 185-192 行(定义)

注:组件统一使用 .surface-2(等价视觉),.glass-panel 保留为兼容别名。

8.2 云烟缭绕边框

选中态组件的动态边框:

  • 常态:石青微弱均匀静态发光
  • hoverconic-gradient 6s 缓慢旋转40-50% 宽弧段),模拟云烟缭绕
  • 移开opacity 600ms 平滑淡散

实现文件: globals.css .glow-border + @property --glow-angle + mistSpin(第 206-285 行) 使用位置: top-nav.tsx 活跃 Tab、session-list.tsx 当前会话

8.3 山雾背景

多层缓慢漂移云雾(远景层 60s / 近景层 45s 两层不同速率和方向模拟远山/近山视差。

实现文件: globals.css .fog-layer-far / .fog-layer-near(第 162-182 行) 挂载位置: ambient-particles.tsx 组件内渲染两个雾层 div

8.4 雾气滚动边缘

主要滚动区域顶底渐变遮罩36px 渐变区域),内容消失在云雾中。

实现文件: globals.css .fog-scroll(第 288-303 行) 使用位置: page.tsx 对话滚动区、session-list.tsx 会话列表


9. 布局架构

整体结构

┌───────────────────────────────────────────────────────┐
│  Top Nav (56px) — Surface-1 + 毛玻璃                    │
├──────────┬────────────────────────────────────────────┤
│  侧边栏    │  主内容区(对话 / 资源库)                    │
│  (280px)  │  (flex-1)                                  │
│  Surface-1 │  ┌──────────────────────────────────────┐ │
│  会话列表   │  │ 对话消息 / 图片网格                     │ │
│  标签筛选   │  │ (fog-scroll 雾气边缘)                  │ │
│           │  └──────────────────────────────────────┘ │
│           │  数据流光条AI 活动时可见)                   │
│           │  输入区 — 水面感应                           │
└──────────┴────────────────────────────────────────────┘

实现文件: page.tsx(首页布局)

间距系统

  • 面板间间距0紧贴用边框分隔
  • 卡片网格间距16px
  • 内容区内边距20px
  • 面板内边距16px

响应式断点

断点 布局
≥768px (md) 双栏:侧边栏(280px) + 主内容区(flex-1)
<768px 单栏:侧边栏为固定抽屉 + 主内容区全宽

实现文件: sidebar.tsxmd 断点切换固定/内联)、app-context.tsxwindow.innerWidth < 768 初始折叠)


10. 技术实现

依赖

  • framer-motion微交互动画引擎spring 物理、stagger、AnimatePresence
  • tailwindcss v4:工具类样式
  • CSS 自定义属性:设计 token
  • CSS @property:可动画角度属性(云烟边框)

文件结构

src/
├── components/ui/
│   ├── ambient-particles.tsx  — 环境萤火粒子 ✅
│   ├── data-stream.tsx        — 数据流光条 ✅
│   ├── ripple-effect.tsx      — 涟漪效果 ✅
│   ├── firefly-burst.tsx      — 萤火粒子爆发 ✅
│   └── motion-presets.ts      — 统一动画参数 ✅
├── app/globals.css            — 设计 token + 工具类 ✅
└── ...existing components     — 集成微交互

性能约束

  • 环境粒子使用 React + CSS animation不引入 Canvas
  • 所有动画使用 transform/opacity避免触发 layout
  • 粒子总数不超过 30 个
  • 背景动效使用 will-change: transform 提示 GPU 加速
  • framer-motion 使用 layout 动画时限制在必要组件