- frontend/: Next.js 16 app (App Router, React 19, Tailwind v4) - skills/: project skills (seedance, automation, trae-agents, etc.) - Docs: PRD, UI-Design-System, DEV-LOG, seedance integration notes - skills-lock.json: skills version lock Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
40 KiB
Air Spark — UI Design System v0.3
2026-03-04 | 经 ui-ux-pro-max skill 审查优化
1. 设计风格定位
核心关键词:Liquid Glass · Cinematic Dark · AI Native · Premium Tool
参考方向:Apple visionOS 2 液态玻璃 + TopNow 极简科技感 视觉目标:让非技术用户一眼觉得"很贵",专业用户觉得"很懂行"
ui-ux-pro-max 风格匹配:Liquid Glass(Score: Best Match)
- Best For: Premium SaaS, creative platforms, branding experiences
- 注意事项:Performance ⚠ Moderate-Poor(需做
prefers-reduced-motion降级)、Accessibility ⚠ Text contrast(需保证 4.5:1)
2. 色彩系统
背景层
| Token | 值 | 用途 |
|---|---|---|
--bg-base |
#07070f |
主背景(深空黑) |
--bg-surface |
#0d0d1a |
表面层 |
--bg-elevated |
#12121f |
抬升层(卡片底) |
玻璃层
| Token | 值 | 用途 |
|---|---|---|
--glass-01 |
rgba(255,255,255,0.04) |
最轻玻璃 |
--glass-02 |
rgba(255,255,255,0.07) |
标准玻璃卡片 |
--glass-03 |
rgba(255,255,255,0.12) |
高亮玻璃(hover) |
--glass-border |
rgba(255,255,255,0.10) |
玻璃描边 |
--glass-border-bright |
rgba(255,255,255,0.20) |
高亮描边 |
品牌 & 强调色
| Token | 值 | 用途 |
|---|---|---|
--accent-primary |
#6c63ff |
紫色(AI / 创意 / 主 CTA) |
--accent-blue |
#3b82f6 |
蓝色(进行中状态) |
--accent-glow |
rgba(108,99,255,0.25) |
紫色光晕 |
状态色
| 状态 | 颜色 | Tailwind | 含义 |
|---|---|---|---|
| pending | 灰 | gray-600 |
队列中 |
| running | 蓝 + 脉冲 | blue-500 + animate-pulse |
生成中 |
| completed | 绿 | emerald-500 |
完成 |
| failed | 红 | red-500 |
失败 |
| waiting | 琥珀 | amber-500 |
等待人工确认 |
文字
| Token | 值 | 用途 |
|---|---|---|
--text-primary |
#f1f0ff |
主文字(微紫色调) |
--text-secondary |
#8b8ea8 |
次要文字 |
--text-muted |
#4c4f6b |
弱化文字 |
3. 玻璃效果规格(CSS)
/* 标准玻璃卡片 */
.glass-card {
background: rgba(255, 255, 255, 0.06);
backdrop-filter: blur(24px) saturate(180%);
-webkit-backdrop-filter: blur(24px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.10);
border-radius: 16px;
box-shadow:
0 0 0 1px rgba(255,255,255,0.05) inset,
0 8px 32px rgba(0,0,0,0.4),
0 1px 0 rgba(255,255,255,0.12) inset;
}
/* 激活/聚焦卡片(带品牌光晕)*/
.glass-card--active {
border-color: rgba(108, 99, 255, 0.4);
box-shadow:
0 0 0 1px rgba(108,99,255,0.2) inset,
0 8px 40px rgba(0,0,0,0.5),
0 0 24px rgba(108,99,255,0.15);
}
/* 主 CTA 按钮 */
.btn-primary {
background: linear-gradient(135deg, #6c63ff 0%, #5b54f0 100%);
box-shadow: 0 0 20px rgba(108,99,255,0.4), 0 4px 12px rgba(0,0,0,0.3);
border: 1px solid rgba(255,255,255,0.15);
border-radius: 12px;
padding: 14px 32px;
}
Tailwind 实现片段
// 玻璃卡片
<div className="bg-white/[0.06] backdrop-blur-2xl border border-white/10 rounded-2xl
shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_8px_32px_rgba(0,0,0,0.4)]
ring-1 ring-inset ring-white/5">
// 主 CTA 按钮(确认类)
<button className="bg-gradient-to-br from-violet-500 to-violet-700
shadow-[0_0_20px_rgba(139,92,246,0.4),0_4px_12px_rgba(0,0,0,0.3)]
border border-white/15 rounded-xl px-8 py-4
text-white font-semibold text-base
hover:shadow-[0_0_30px_rgba(139,92,246,0.6)] transition-all duration-200
active:scale-[0.98] cursor-pointer">
// 生成中状态格子(蓝·脉冲)
<div className="bg-blue-500/20 border border-blue-400/40 rounded-lg animate-pulse
ring-1 ring-blue-400/30">
// 完成状态格子
<div className="bg-emerald-500/15 border border-emerald-400/30 rounded-lg">
// 失败状态格子
<div className="bg-red-500/15 border border-red-400/30 rounded-lg">
固定层叠规范(Fixed Overlay)
固定定位元素(navbar、sidebar、modal)滚动时会与页面内容重叠。 为保持"半透不全透"的高级感,统一使用 bg-base 色 + 高不透明度 + blur,而非纯 glass-card:
| 元素 | 背景 | 模糊 | 边框 |
|---|---|---|---|
| Navbar | rgba(7, 7, 15, 0.85) |
blur(20px) saturate(180%) |
border-b border-white/[0.06] |
| Sidebar | rgba(7, 7, 15, 0.80) |
blur(16px) saturate(160%) |
border-r border-white/[0.06] |
| Modal backdrop | rgba(0, 0, 0, 0.60) |
blur(8px) |
无 |
| Modal panel | rgba(13, 13, 26, 0.92) |
blur(24px) saturate(180%) |
border border-white/[0.08] |
核心原则:
- 背景色取自
--bg-base或--bg-surface,不透明度 ≥ 0.80(保证可读) - 搭配
backdrop-filter: blur让底层内容产生柔和虚化(高级感来源) - 不使用纯
glass-card(0.06 不透明度太低,重叠时文字会模糊)
// Navbar 标准写法
<nav className="fixed top-0 left-0 right-0 z-30 border-b border-white/[0.06]"
style={{
background: 'rgba(7, 7, 15, 0.85)',
backdropFilter: 'blur(20px) saturate(180%)',
WebkitBackdropFilter: 'blur(20px) saturate(180%)',
}}>
4. 字体系统
| 用途 | 字体 | CSS 变量 | 字重 | 备注 |
|---|---|---|---|---|
| 大标题 / Display | Space Grotesk | --font-heading |
700 | 科技感,棱角干净(skill "Tech Startup" 首选) |
| 标题 H1-H3 | Space Grotesk | --font-heading |
600-700 | |
| 正文 / UI 文字 | DM Sans | --font-body |
400-600 | 几何感更强,比 Inter 更 premium,与 Space Grotesk 配合更和谐 |
| 代码 / ID / 时码 | JetBrains Mono | --font-mono |
400 | 技术细节标注 |
| 中文文字 | Noto Sans SC(思源黑体) | --font-cn |
400-700 | Google Fonts 免费中文字体,与 DM Sans 风格匹配 |
中文 fallback 策略:英文字体栈末尾统一追加
"Noto Sans SC"作为 fallback,中文字符自动命中。 需要纯中文排版时使用--font-cn("Noto Sans SC", "DM Sans", sans-serif)。
Google Fonts 导入:
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400&family=Noto+Sans+SC:wght@400;500;600;700&display=swap');
CSS 变量(globals.css @theme inline):
--font-heading: "Space Grotesk", "Noto Sans SC", sans-serif;
--font-body: "DM Sans", "Noto Sans SC", sans-serif;
--font-mono: "JetBrains Mono", monospace;
--font-cn: "Noto Sans SC", "DM Sans", sans-serif;
字号阶梯:
- Display: 48px / 700 / letter-spacing: -0.02em
- H1: 32px / 700 / -0.01em
- H2: 24px / 600
- H3: 18px / 600
- Body: 15px / 400 / line-height: 1.6
- Small: 13px / 400
- Mono: 13px / 400
关键规则:
- 所有字体必须加
font-display: swap,避免 FOIT(Flash of Invisible Text) - Body 文字 line-height: 1.6,行宽上限 65-75 字符
5. 图标 & 视觉元素
| 规则 | 标准 |
|---|---|
| 图标库 | Lucide Icons(SVG,统一 24x24 viewBox,Tailwind w-5 h-5 或 w-6 h-6) |
| 禁止 Emoji | 不使用 emoji 作为 UI 图标,全部用 SVG |
| 品牌 Logo | 从 Simple Icons 获取官方 SVG |
| Hover 状态 | 只用 color/opacity/shadow 过渡,不用 scale(避免布局偏移) |
| 交互元素 | 所有可点击元素加 cursor-pointer |
6. z-index 管理
| 层级 | z-index | 用途 |
|---|---|---|
| 基础内容 | 0 |
正常文档流 |
| 浮动卡片 | 10 |
弹出面板、dropdown |
| Sticky 步骤条 | 20 |
流水线步骤条 |
| 顶部导航栏 | 30 |
全局导航 |
| 模态框遮罩 | 40 |
Modal overlay |
| 模态框内容 | 50 |
Modal content |
| Toast 通知 | 60 |
全局提示 |
7. 页面结构
7.1 整体布局
┌──────────────── 顶部导航栏(玻璃,fixed)────────────────┐
│ [⚡ Air Spark] 项目名 / 集数 [设置] [成员] │
└──────────────────────────────────────────────────────────┘
┌──────────── 流水线步骤条(横向,sticky)─────────────────┐
│ ①剧本 ══► ②规划 ══► ③人设 ══► ④分镜 ══► ⑤切分 ══► ⑥生成 ══► ⑦剪辑 │
│ ✓完成 ✓完成 ⚠待确认 ○待机 ○待机 ○待机 ○待机 │
└──────────────────────────────────────────────────────────┘
┌──────────────── 当前阶段主内容区 ───────────────────────┐
│ [阶段标题] │
│ [内容区域 — 根据阶段变化] │
│ [底部 CTA 区域] │
└──────────────────────────────────────────────────────────┘
┌──────── 系统日志(可折叠,默认收起)────────────────────┐
│ ▶ 系统日志 [展开] │
└──────────────────────────────────────────────────────────┘
7.2 Pipeline View — 主流水线页
┌─────────────────────────────────────────────────────────────────────────┐
│ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ ░ [⚡ Air Spark] T仔的上班日记 / EP01 [设置] [成员] ░ │
│ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ │
│ ┌──────────────── 流水线进度条 ──────────────────────────────────┐ │
│ │ ①剧本 ══► ②规划 ══► ③人设 ══► ④分镜 ══► ⑤切分 ══► ⑥生成 ══► ⑦剪辑│ │
│ │ ✓完成 ✓完成 ⚠待确认 ○待机 ○待机 ○待机 ○待机 │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────── 当前阶段内容区 ────────────────────────────┐ │
│ │ │ │
│ │ 【Stage 3 — 人设图审核】 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │░░░░░░░░░│ │░░░░░░░░░│ │░░░░░░░░░│ │░░░░░░░░░│ │ │
│ │ │ T仔 │ │ 特特 │ │ 班长 │ │ 路人甲 │ │ │
│ │ │ 人设三视│ │ 人设三视│ │ 人设三视│ │ ⚠生成失败│ │ │
│ │ │ [✓ 通过]│ │ [✓ 通过]│ │ [✓ 通过]│ │ [↻ 重跑] │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────┐ │ │
│ │ │ ⚠ 路人甲生成失败,重跑后可确认 │ │ │
│ │ │ │ │ │
│ │ │ [ 等待路人甲重跑完成... ] ← CTA 灰色禁用 │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌── 日志(可折叠)─────────────────────────────────────────────────┐ │
│ │ ▶ 系统日志 [展开]│ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
8. Stage 6 — 视频生成进度界面
┌─────────────────────────────────────────────────────────────────────────┐
│ 【Stage 6 — 视频生成中】 已完成 18 / 32 片段 │
│ │
│ ████████████████████░░░░░░░░░░░░░░░░░ 56% 预计剩余 ~8 分钟 │
│ │
│ ┌──────────────────────── 片段状态网格 ────────────────────────────┐ │
│ │ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 01 │ │ 02 │ │ 03 │ │ 04 │ │ 05 │ │ 06 │ │ 07 │ │ 08 │ │ │
│ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✗ │ │ │
│ │ │ 绿 │ │ 绿 │ │ 绿 │ │ 绿 │ │ 绿 │ │ 绿 │ │ 绿 │ │ 红 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │ 09 │ │ 10 │ │ 11 │ │ 12 │ │ 13 │ │ 14 │ │ 15 │ │ 16 │ │ │
│ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ✓ │ │ ● │ │ ● │ │ ● │ │ ● │ │ │
│ │ │ 绿 │ │ 绿 │ │ 绿 │ │ 绿 │ │蓝脉│ │蓝脉│ │蓝脉│ │蓝脉│ │ │
│ │ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ... │ │
│ │ │ 17 │ │ 18 │ │ 19 │ │ 20 │ │ 21 │ │ │
│ │ │ ● │ │ ● │ │ ○ │ │ ○ │ │ ○ │ │ │
│ │ │蓝脉│ │蓝脉│ │ 灰 │ │ 灰 │ │ 灰 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ └────┘ │ │
│ │ │ │
│ │ 图例: ✓绿 完成 ●蓝 生成中(脉冲) ○灰 队列中 ✗红 失败 │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─── 失败片段处理 ──────────────────────────────────────────────────┐ │
│ │ ⚠ 片段08 — 生成失败(重试3次后超时) [编辑提示词] [↻ 重跑] │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
9. 人工确认交互规范
核心原则
确认时清场噪音,只留一个决策。CTA 状态变化(灰→绿)有动画。确认后 3 秒防误触。
Stage 1 — 剧本确认
对话区(主体)
↓ 剧本满意后底部出现确认栏
┌──────────────────────────────────────────────────────────┐
│ ✅ 剧本已就绪 — 共 8 场景,预估 4 分 20 秒 │
│ │
│ ╔══════════════════════════════════════════════════╗ │
│ ║ 确认剧本,启动流水线 ▶ ║ │ ← 大按钮,紫色发光
│ ╚══════════════════════════════════════════════════╝ │
│ │
│ [继续修改剧本] │ ← 小字次级操作
└──────────────────────────────────────────────────────────┘
Stage 3 — 人设确认
- 每张图独立操作:
[✓ 通过]/[↻ 重跑] - 支持单张图
[编辑提示词后重跑] - 底部汇总 CTA:所有图通过 → 按钮从灰色变绿色发光 → 可点击
- 点击确认后:按钮显示 "3s 后启动..." +
[取消]防误触
自动阶段(Stage 2/4/5)
- 骨架屏优先:超过 300ms 的异步操作,显示 Skeleton 占位(不是空白)
- 进度文字("正在规划场景结构...")+ 预估时间
- 完成后自动高亮 CTA 或自动推进(取决于流水线模式)
- 无需用户操作,只展示状态
Skeleton 实现:
// 骨架屏卡片
<div className="bg-white/[0.04] rounded-2xl animate-pulse">
<div className="h-40 bg-white/[0.06] rounded-t-2xl" />
<div className="p-4 space-y-3">
<div className="h-4 bg-white/[0.08] rounded w-3/4" />
<div className="h-3 bg-white/[0.06] rounded w-1/2" />
</div>
</div>
10. 动效规范
| 场景 | 时长 | Easing |
|---|---|---|
| 卡片 hover | 150ms | ease-out |
| CTA 状态变化(灰→绿) | 300ms | ease-in-out |
| 片段格子状态更新 | 200ms | ease-out |
| 步骤条推进动画 | 400ms | ease-in-out |
| 页面切换 | 250ms | ease-in-out |
| 脉冲动画(running 状态) | 1500ms | ease-in-out,循环 |
| 玻璃形变动效(Liquid Glass) | 400-600ms | cubic-bezier(0.16, 1, 0.3, 1) |
性能降级(必须):
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Tailwind 实现:
// 所有动画组件加上 motion-safe 前缀
<div className="motion-safe:animate-pulse ..." />
<div className="motion-safe:transition-all motion-safe:duration-200 ..." />
规则:
- 微交互:150-300ms(hover、click 反馈)
- 状态变化:300-400ms(步骤推进、CTA 变化)
- 液态玻璃:400-600ms(morphing、blur 变化)
- 装饰动画仅用于 loading,不用于静态元素
- 所有 animation 用
transform和opacity,不用width/height/top/left
11. 无障碍 & 可用性规范(CRITICAL)
| 规则 | 标准 |
|---|---|
| 文字对比度 | 主文字 #f1f0ff on #07070f = 18.5:1 ✅ 远超 WCAG AAA |
| 次要文字对比度 | #8b8ea8 on #07070f = 6.2:1 ✅ 超 AA |
| 弱化文字对比度 | #4c4f6b on #07070f = 3.1:1 ⚠ 仅用于装饰性标注,不用于关键信息 |
| Focus 焦点环 | 所有交互元素:focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 focus-visible:ring-offset-[#07070f] |
| 键盘导航 | Tab 顺序 = 视觉顺序;步骤条、片段网格支持方向键导航 |
| 按钮最小尺寸 | 44×44px 点击区域(移动端和桌面端均适用) |
| 颜色不作为唯一标识 | 状态除颜色外,必须有图标/文字辅助(✓/●/○/✗ + 文字标签) |
| aria-label | 图标按钮(设置、重跑、展开)必须有 aria-label |
| 表单标签 | 所有 input 必须关联 <label> |
12. 交付前质检清单
视觉质量
- 无 emoji 作为图标(全部 Lucide SVG)
- 所有图标来自同一套图标库,尺寸一致
- Hover 状态不引起布局偏移
- 玻璃卡片在深色背景上有足够可见度
交互
- 所有可点击元素有
cursor-pointer - Hover 有明确视觉反馈(150-300ms 过渡)
- Focus 焦点环对键盘用户可见
- 异步操作 > 300ms 时显示 Skeleton 骨架屏
性能
prefers-reduced-motion降级已实现- 图片使用 WebP + lazy loading
- 字体
font-display: swap - 重组件使用
next/dynamic动态导入 - Bundle 分析通过(
@next/bundle-analyzer)
响应式
- 375px / 768px / 1024px / 1440px 四档断点测试
- 无横向滚动条
- 固定导航栏不遮挡内容(留 padding-top)
13. 间距系统
基于 4px 基础单位,所有间距从以下阶梯中选取:
| Token | 值 | 用途 |
|---|---|---|
space-1 |
4px | 图标与文字间距、紧凑元素内间距 |
space-2 |
8px | 相关元素组内间距(如标签+输入框) |
space-3 |
12px | 卡片内边距(紧凑型)、列表项间距 |
space-4 |
16px | 标准卡片内边距、表单字段间距 |
space-6 |
24px | 卡片内边距(宽松型)、区块间距 |
space-8 |
32px | Section 之间的间距 |
space-12 |
48px | 大区块间距 |
space-16 |
64px | 页面级 section 间距 |
核心原则:
- 同组元素用
space-2~space-3(紧密关联) - 不同组件之间用
space-6~space-8(视觉分隔) - 页面容器统一
px-6(24px 左右内边距)、max-w-7xl mx-auto
// Tailwind 对照
<div className="p-4"> // space-4 = 16px
<div className="p-6"> // space-6 = 24px
<div className="gap-3"> // space-3 = 12px
<div className="mb-8"> // space-8 = 32px
<section className="mb-16"> // space-16 = 64px(页面级)
14. 圆角系统
| Token | 值 | 用途 |
|---|---|---|
radius-sm |
6px | 小元素(tag、badge、输入框) |
radius-md |
8px | 按钮、小卡片、下拉菜单 |
radius-lg |
12px | 中型卡片、CTA 按钮 |
radius-xl |
16px | 主内容卡片(glass-card 默认) |
radius-2xl |
24px | 大面板、模态框 |
radius-full |
9999px | 头像、圆形按钮、pill tag |
// Tailwind 对照
rounded-md // 6px → tag, badge, input
rounded-lg // 8px → 按钮
rounded-xl // 12px → CTA
rounded-2xl // 16px → glass-card
rounded-3xl // 24px → modal
rounded-full // pill
核心原则:
- 嵌套元素的子级圆角 = 父级圆角 - 父级内边距(避免嵌套圆角溢出)
- 同层级元素圆角保持一致
15. 表单元素
Input / Textarea
.form-input {
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.10);
border-radius: 8px;
padding: 12px 16px;
color: var(--text-primary);
font-size: 15px;
line-height: 1.5;
transition: border-color 200ms ease, box-shadow 200ms ease;
}
.form-input:focus {
outline: none;
border-color: rgba(108, 99, 255, 0.5);
box-shadow: 0 0 0 3px rgba(108, 99, 255, 0.15);
}
.form-input::placeholder {
color: var(--text-muted);
}
.form-input--error {
border-color: rgba(239, 68, 68, 0.5);
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.12);
}
Tailwind 实现
// 标准输入框
<input className="w-full bg-white/[0.04] border border-white/10 rounded-lg
px-4 py-3 text-[15px] text-text-primary placeholder:text-text-muted
focus:outline-none focus:border-accent/50 focus:ring-3 focus:ring-accent/15
transition-all duration-200" />
// 错误状态
<input className="... border-red-500/50 focus:ring-red-500/12" />
// 多行输入(剧本对话)
<textarea className="w-full bg-white/[0.04] border border-white/10 rounded-lg
px-4 py-3 text-[15px] text-text-primary placeholder:text-text-muted
focus:outline-none focus:border-accent/50 focus:ring-3 focus:ring-accent/15
transition-all duration-200 resize-none min-h-[120px]" />
// Label
<label className="block text-sm font-medium text-text-secondary mb-2">
Select / Dropdown
禁止使用原生
<select>——弹出菜单无法自定义样式(白底,破坏暗色主题)。 必须使用自定义 dropdown 组件。
// 触发按钮
<button className="w-full bg-white/[0.04] border border-white/10 rounded-lg
px-4 py-3 text-[15px] text-text-primary text-left flex items-center justify-between
cursor-pointer transition-all duration-200
// 展开时:
border-accent/50 ring-3 ring-accent/15">
{selectedValue}
<ChevronsUpDown className="w-4 h-4 text-text-muted" />
</button>
// 下拉面板(absolute, z-20)
<div className="absolute z-20 mt-1 w-full rounded-lg border border-white/10 overflow-hidden"
style={{ background: 'rgba(13, 13, 26, 0.95)', backdropFilter: 'blur(20px)' }}>
// 选项
<button className="w-full px-4 py-2.5 text-[15px] text-left
text-text-primary hover:bg-white/[0.06]
// 选中态:text-accent bg-accent/10">
</div>
表单规则
- Label 在 input 上方,间距
mb-2(8px) - 字段之间间距
space-y-4(16px) - 错误信息在字段下方,
text-sm text-red-400 mt-1 - 必填标识用
*+text-red-400,不用颜色作为唯一标识 - 所有 input 必须有关联
<label>(无障碍要求)
16. Toast 通知
类型与样式
| 类型 | 图标 | 左边框色 | 用途 |
|---|---|---|---|
| success | Check (Lucide) |
emerald-500 |
操作成功、保存完成 |
| error | X (Lucide) |
red-500 |
操作失败、API 错误 |
| warning | AlertTriangle |
amber-500 |
需要注意、即将超时 |
| info | Info (Lucide) |
blue-500 |
提示信息、状态更新 |
行为规范
- 位置:屏幕右下角,距底 24px、距右 24px
- 多条堆叠:从下往上,间距 8px
- 自动消失:success/info = 4s,warning = 6s,error = 不自动消失(需手动关闭)
- 进入动画:从右侧滑入 + fade in(250ms, ease-out)
- 退出动画:向右滑出 + fade out(200ms, ease-in)
Tailwind 实现
// Toast 容器
<div className="fixed bottom-6 right-6 z-60 flex flex-col-reverse gap-2">
// 单条 Toast
<div className="glass-card px-4 py-3 flex items-start gap-3 min-w-[320px] max-w-[420px]
border-l-3 border-l-emerald-500
animate-[slideInRight_250ms_ease-out]">
<Check className="w-5 h-5 text-emerald-400 mt-0.5 shrink-0" />
<div className="flex-1">
<p className="text-sm font-medium text-text-primary">保存成功</p>
<p className="text-xs text-text-secondary mt-0.5">剧本已保存为正式版本</p>
</div>
<button className="text-text-muted hover:text-text-secondary cursor-pointer"
aria-label="关闭通知">
<X className="w-4 h-4" />
</button>
</div>
17. 空状态
当列表/内容区域无数据时,统一显示空状态占位。
结构
┌──────────────────────────────────────┐
│ │
│ [Lucide 图标 48px] │
│ │
│ 主标题(简短描述) │
│ 副标题(下一步指引) │
│ │
│ [ 主操作按钮 ] │
│ │
└──────────────────────────────────────┘
场景预设
| 场景 | 图标 | 主标题 | CTA |
|---|---|---|---|
| 项目列表为空 | FolderPlus |
还没有项目 | 创建第一个项目 |
| 资产库为空 | ImagePlus |
暂无资产 | 在流水线中生成 |
| 剧集列表为空 | Film |
还没有剧集 | 添加第一集 |
| 搜索无结果 | SearchX |
没有找到匹配项 | 试试其他关键词 |
| 视频片段为空 | VideoOff |
暂无视频片段 | 运行 Stage 6 生成 |
Tailwind 实现
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="w-12 h-12 rounded-2xl bg-white/[0.04] flex items-center justify-center mb-4">
<FolderPlus className="w-6 h-6 text-text-muted" />
</div>
<h3 className="font-[family-name:var(--font-heading)] text-lg font-semibold text-text-primary mb-1">
还没有项目
</h3>
<p className="text-sm text-text-secondary mb-6">
创建你的第一个动画项目,开始 AI 创作之旅
</p>
<button className="bg-gradient-to-br from-violet-500 to-violet-700
border border-white/15 rounded-xl px-6 py-2.5
text-sm text-white font-medium
hover:shadow-[0_0_20px_rgba(139,92,246,0.4)] transition-all duration-200
cursor-pointer">
创建项目
</button>
</div>
规则
- 图标用
text-muted色(不要太抢眼) - 主标题简短(≤10 字)
- 副标题给出明确的下一步指引
- 必须有 CTA 按钮引导操作(除"搜索无结果"外)
18. 响应式断点
MVP 优先桌面端(1024px+),移动端后续规划。
| 断点 | Tailwind 前缀 | 宽度 | 用途 |
|---|---|---|---|
| Mobile | 默认(无前缀) | < 768px | 未来适配 |
| Tablet | md: |
≥ 768px | 简单适配(单栏布局) |
| Desktop | lg: |
≥ 1024px | 主设计目标 |
| Wide | xl: |
≥ 1280px | 宽屏优化 |
| Ultra-wide | 2xl: |
≥ 1536px | 超宽屏留白控制 |
布局适配规则
| 元素 | < 768px | 768px+ | 1024px+ | 1280px+ |
|---|---|---|---|---|
| 导航栏 | 汉堡菜单 | 完整导航 | 完整导航 | 完整导航 |
| 内容容器 | px-4 |
px-6 |
max-w-6xl mx-auto |
max-w-7xl mx-auto |
| 审核卡片网格 | 1 列 | 2 列 | 3 列 | 4 列 |
| 片段状态网格 | 4 列 | 6 列 | 8 列 | 8 列 |
| Pipeline Stepper | 纵向列表 | 横向滚动 | 横向完整 | 横向完整 |
核心原则
- Mobile-first 写法:默认写移动端样式,用
md:lg:向上覆盖 - 内容区
max-w-7xl(1280px),超宽屏两侧自然留白 - 卡片网格用
grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 - 固定导航栏高度不变(h-16 = 64px),所有断点保持一致
- 文字不缩放(最小 body 15px),只调整布局
19. Badge / Tag
状态 Badge(方角)
用于流水线阶段状态、任务状态等系统状态标识。
// 结构:icon + 文字,圆角 rounded-md,带边框
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md
text-xs font-medium bg-emerald-500/15 text-emerald-400 border border-emerald-400/20">
<Check className="w-3 h-3" /> Completed
</span>
| 状态 | 背景 | 文字 | 边框 |
|---|---|---|---|
| completed | emerald-500/15 |
emerald-400 |
emerald-400/20 |
| running | blue-500/15 |
blue-400 |
blue-400/20 |
| waiting | amber-500/15 |
amber-400 |
amber-400/20 |
| failed | red-500/15 |
red-400 |
red-400/20 |
| pending | white/[0.06] |
text-secondary |
white/10 |
内容 Tag(圆角 pill)
用于 Skill 标签、剧集标签等内容分类。
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full
text-xs font-medium bg-accent/15 text-accent border border-accent/20">
<Hash className="w-3 h-3" /> screenplay-skill
</span>
20. Avatar
尺寸
| 尺寸 | Tailwind | 用途 |
|---|---|---|
| SM | w-8 h-8 text-xs |
紧凑列表、评论 |
| MD | w-10 h-10 text-sm |
默认(导航栏、成员列表) |
| LG | w-12 h-12 text-base |
个人资料 |
| XL | w-16 h-16 text-lg |
设置页头像 |
样式
// 带字母(首选)
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-violet-500 to-accent-blue
flex items-center justify-center text-sm font-semibold text-white">
T
</div>
// 空白 fallback
<div className="w-10 h-10 rounded-full bg-white/[0.06] border border-white/10
flex items-center justify-center">
<User className="w-5 h-5 text-text-muted" />
</div>
// 在线状态指示
<div className="relative">
{/* avatar */}
<div className="absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full
bg-emerald-500 border-2 border-bg-base" />
</div>
// Avatar Group(重叠)
<div className="flex -space-x-2">
{avatars.map((a, i) => (
<div key={i} className="... border-2 border-bg-base" />
))}
<div className="... bg-white/[0.08] text-xs text-text-secondary">+3</div>
</div>
21. Breadcrumb
<nav aria-label="Breadcrumb" className="flex items-center gap-2 text-sm">
<a className="text-text-secondary hover:text-text-primary transition-colors cursor-pointer">
Projects
</a>
<ChevronRight className="w-3.5 h-3.5 text-text-muted" />
<a className="text-text-secondary hover:text-text-primary transition-colors cursor-pointer">
T仔的上班日记
</a>
<ChevronRight className="w-3.5 h-3.5 text-text-muted" />
<span className="text-text-primary font-medium">Pipeline</span>
</nav>
规则:
- 最后一级为当前页面,用
text-primary font-medium,不可点击 - 分隔符用
ChevronRight(Lucide),text-muted - 必须有
aria-label="Breadcrumb"的<nav>包裹
22. Tab / Segmented Control
Underline Tabs
<div className="flex border-b border-white/10">
<button className={`px-4 py-3 text-sm font-medium relative cursor-pointer
${active ? "text-accent" : "text-text-secondary hover:text-text-primary"}`}>
{label}
{active && <div className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent rounded-full" />}
</button>
</div>
Segmented Control(Pill 风格)
<div className="inline-flex bg-white/[0.04] rounded-lg p-1 border border-white/[0.06]">
<button className={`px-4 py-2 rounded-md text-sm font-medium cursor-pointer
${active ? "bg-accent/20 text-accent shadow-sm" : "text-text-secondary hover:text-text-primary"}`}>
{label}
</button>
</div>
规则:
- Tab 切换内容区域,不跳转页面
- 激活态下划线/背景色用 accent
- 所有 tab 按钮加
cursor-pointer
23. Danger Button
破坏性操作(删除项目、清空资产)专用按钮。
// 默认 Danger(轻量,用于非终极操作)
<button className="bg-red-500/15 border border-red-400/30 rounded-xl px-6 py-3
text-[15px] font-medium text-red-400 hover:bg-red-500/25 transition-colors cursor-pointer
flex items-center gap-2">
<Trash2 className="w-4 h-4" /> Delete Project
</button>
// 确认 Danger(实心红色,用于二次确认后的终极操作)
<button className="bg-red-600 border border-red-500 rounded-xl px-6 py-3
text-[15px] font-medium text-white hover:bg-red-700 transition-colors cursor-pointer">
Confirm Delete
</button>
规则:
- 破坏性操作必须先弹 Modal 确认,再执行
- 默认展示轻量 danger(红色文字 + 透明底),确认时切换为实心红底
- Focus ring 用
ring-red-400
24. Search Input
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted" />
<input type="text" placeholder="Search projects, episodes..."
className="w-full bg-white/[0.04] border border-white/10 rounded-lg
pl-10 pr-4 py-3 text-[15px] text-text-primary placeholder:text-text-muted
focus:outline-none focus:border-accent/50 focus:ring-3 focus:ring-accent/15
transition-all duration-200" />
</div>
规则:
- 搜索图标左侧内嵌,
left-3,输入区域pl-10 - 图标用
text-muted,输入时不变色 - 与标准 input 共享 focus 样式
25. Tooltip
// 使用 CSS group/hover,无需 JS
<div className="group relative">
<button className="p-2.5 rounded-xl glass-card hover:bg-white/[0.12]
transition-colors cursor-pointer" aria-label="Settings">
<Settings className="w-5 h-5 text-text-secondary" />
</button>
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2
px-3 py-1.5 rounded-lg text-xs font-medium text-text-primary whitespace-nowrap
opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none
border border-white/10"
style={{ background: 'rgba(13, 13, 26, 0.95)', backdropFilter: 'blur(12px)' }}>
Project Settings
{/* 箭头 */}
<div className="absolute top-full left-1/2 -translate-x-1/2
w-2 h-2 rotate-45 border-b border-r border-white/10"
style={{ background: 'rgba(13, 13, 26, 0.95)' }} />
</div>
</div>
位置变体:
- Top:
bottom-full mb-2+ 箭头top-full border-b border-r - Right:
left-full ml-2+ 箭头right-full border-l border-b - Bottom:
top-full mt-2+ 箭头bottom-full border-t border-l - Left:
right-full mr-2+ 箭头left-full border-r border-t
规则:
- 背景用 Fixed Overlay 规范:
rgba(13, 13, 26, 0.95)+blur(12px) - 纯 CSS 实现(
group-hover:opacity-100),无需 JS 状态 pointer-events-none防止 tooltip 干扰点击- 图标按钮必须同时有
aria-label(tooltip 仅视觉增强,不替代无障碍)
26. 待确认项
- Stage 7 时间轴编辑器的具体 UI 细节(片段缩略图、拖拽交互、波形显示)
- 移动端适配策略(内部工具优先级低,先做 1024px+ 桌面端)
- 浅色模式:当前纯暗色,MVP 不做浅色切换