用途
本技能用于为 Expo 应用构建结构化设计系统,将颜色、字体、间距、圆角、阴影、动效等视觉值集中管理。它强调单一数据源、语义化角色以及代码级的可验证规则,确保明暗模式、对比度、字体缩放等关键质量属性得到保障。
主要能力
- 双层 Token 体系:
design/tokens.json存放基础值(第一层)和语义角色(第二层),所有主题模块复制该文件,并通过检查器比对值的一致性。 - 明暗色板与对比度验证:
write-palette.mjs根据对比度要求生成色板,只有所有配对(文本 4.5:1,边缘/焦点/图标 3:1)通过才写入palette.ts;对比度配对在contracts/contrast.json中声明,由 Jest 测试维护。 - 主题提供器与导航集成:
AppThemeProvider解析系统偏好并同步到Appearance,根视图背景随主题变化;NavigationThemeProvider为导航器提供主题颜色,避免使用裸DarkTheme/DefaultTheme。 - 样式工厂与文本组件:
makeStyles基于StyleSheet.create构建并缓存,保留类型检查;AppText强制使用预设字体角色,禁止原始fontSize或letterSpacing,行高按像素网格对齐,支持平衡换行与高文字缩放。 - 字体管理:默认使用系统字体;可选捆绑字体,需按 PostScript 名称命名文件并记录 sha256,通过 expo-font 插件嵌入,每个字重单独定义字族。
- 动效 Token:时长和弹簧参数只能来自 token,弹簧必须完整定义阻尼、刚度、质量,并提供减少动效的替代方案。
- 按压表面:
PressableSurface统一处理按压效果、Android ripple、禁用样式和无障碍状态,视觉样式由 token 决定,持久按压状态使用布局偏移而非 transform。 - 检查器:
check-design-system.mjs和check-raw-values.mjs扫描代码,确保主题与 token 一致、无原始颜色/尺寸/阴影/动效值、无第二套主题系统。
使用方式
- 检测项目是否已有其他样式系统(如 NativeWind、Tamagui),若有则跳过并沿用原系统。
- 复制模板中的
src/theme/、src/ui/、contracts/和design/到应用对应路径,替换 demo 值为设计值。 - 运行
node ${CLAUDE_SKILL_DIR}/scripts/write-palette.mjs . --dry-run验证色板对比度,通过后移除--dry-run生成palette.ts。 - 配置
app.config.ts中userInterfaceStyle: 'automatic',安装expo-system-ui,在根布局挂载AppThemeProvider和NavigationThemeProvider。 - 使用
makeStyles和AppText编写组件,遵循 token 引用规则。 - 运行类型检查、ESLint、Jest 及检查器脚本,确保全部通过。
适用场景
- 新建 Expo 应用需要建立可维护的设计系统。
- 已有项目需要迁移至集中式主题管理,消除硬编码样式。
- 对可访问性(对比度、字体缩放、动效减少)有严格要求的应用。
- 需要跨 iOS 和 Android 保持视觉一致性的项目。
限制
- 仅适用于 Expo 应用,且检查器假设项目使用 React Native 和 StyleSheet。
- 若项目已使用其他样式系统(如 NativeWind),检查器将输出 NOT APPLICABLE,需沿用原有系统。
- 要求设计值必须来自 token 文件,任何直接硬编码的值都会被检查器标记为失败。
- 色板生成依赖对比度合约,修改颜色需通过 token 文件并重新生成,不能直接编辑配对表。
- 字体捆绑需手动处理文件命名、许可和哈希记录,系统字体为默认选项。