关于 mobile-taste
mobile-taste 是一项用于构建跨平台 React Native 应用界面、导航和组件的技能。它要求先理解产品需求并检查现有技术栈,再作出设计与实现选择。
主要功能
- 01从需求推断应用定位
- 02检查现有项目技术栈
- 03先规划导航再设计界面
- 04设定表现、动效与信息密度
- 05将设计决策记录到 MOBILE-DESIGN.md
- 06按情境选用移动端设计指导
适用场景
- 01构建新移动应用的界面
- 02制定导航与组件方案
- 03沿用应用现有技术栈继续开发
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ draftbit/ mobile-taste-skill --skill mobile-taste安装后在 Claude Code 中输入/mobile-taste确认已加载。
详细介绍
mobile-taste:反套路 React Native 技能
跨平台移动应用:屏幕、导航、组件、动效。不适用于营销网站(请使用原版 taste-skill)、游戏或原生模块。 以下规则均需结合上下文判断,不会自动触发。先阅读需求说明, 再挑选适用的规则。
同系列技能(按任务拆分):mobile-design-review(审核现有应用)、mobile-redesign-screen / mobile-redesign-app(升级现有 UI)、mobile-nav-plan(仅规划导航架构)、mobile-design-system(设计令牌 + 主题)。此技能用于构建。
更深入的参考资料,按需加载:
../_shared/references/navigation.md- 导航决策树、Expo Router 约定、导航阅读示例../_shared/references/skeletons.md- 针对 LLM 常出错模式的标准 Reanimated/手势代码../_shared/references/tells.md- 完整的套路特征目录(只增不删)+ 可运行的 grep 检查清单../_shared/references/versions.md- 所有与版本相关的事实(SDK 配套关系、软件包主版本)。本文件有意不注明任何版本。../_shared/blocks/- 经验证的屏幕模式实现(架构见第 12 节)
0. 应用理解(先读懂情境,再做其他事)
动手改代码前,先推断用户真正想要什么。大多数 LLM 生成的移动应用效果很差,因为模型会直接套用默认模板(靛蓝渐变、5 个标签页、卡片堆叠),而不是先读懂情境。
0.0 技术栈探查(在现有项目中,先于需求理解)
首先阅读 package.json、app.json 和任何 Tailwind/主题配置。识别:Expo SDK、路由方案(Expo Router 还是 React Navigation)、样式方案(NativeWind、StyleSheet、Tamagui 还是 Paper)、图标系列、现有主题令牌,以及是否存在 MOBILE-DESIGN.md(0.E)——如果存在,请阅读并将其中的约定视为既定要求。检测到的技术栈优先于本技能中的所有默认设置。第一版代码若导入了错误的样式系统,就完全白费了;花 30 秒探查就能避免这种情况。
0.A 先读取这些信号
- 应用类型 - 消费级社交、实用工具、健身/健康、金融科技、电子商务、内容/媒体、生产力、儿童、现场/运营工具。
- 风格关键词 - “简洁”“活泼”“高端”“iOS 原生感”“像 Airbnb”“信息密集/专业”“平静”“品牌感强”。
- 用户提到的参考应用。在移动端,真实应用就如同参考网站之于 Web,是设计语言的参照。
- 受众与使用情境 - 在火车上单手操作、在沙发上双手操作,还是在现场戴手套操作。情境决定信息密度和目标尺寸,而不是你的个人偏好。
- 目标平台 - iOS / Android / Web,以及哪个平台是首要平台。
- 不易察觉的约束 - 优先考虑无障碍的用户、儿童(更大的目标尺寸,不使用暗黑模式设计)、受监管场景(金融科技/健康领域的信息披露模式)、重度离线使用。
0.B 生成前先输出应用理解
APP READ: <app kind> for <audience>, <vibe> language, leaning <design language / stack>.
platforms: iOS first-class · Android first-class · web best-effort
posture: unified-brand | iOS-first | Android-first | per-platform-native
示例:“应用理解:面向忙碌职场人士的习惯追踪工具,语言平静简约,倾向采用 NativeWind + 原生界面。平台:iOS + Android 均为首要平台,不支持 Web。设计取向:统一品牌。”
平台取向是一项明确约定:per-platform-native 表示组件因平台而异(SF Symbols 与 Material 图标、iOS 开关与 Material 开关);unified-brand 表示所有平台使用统一外观,底层采用原生导航界面。
0.C 如果需求说明含糊,只问一个问题,不要猜
仅当不同理解确实会导致明显分歧时提问(例如:“你希望它像 Things 一样具有 iOS 原生感,还是像 Duolingo 一样突出品牌风格?”)。如果能够确信地推断出来,就先说明应用理解,再继续。
0.D 避免默认套路
不要默认采用:靛蓝/紫罗兰渐变、带居中 FAB 的 5 标签栏、每个屏幕都由白色圆角卡片堆成、用表情符号充当图标、三页插画式引导流程、“欢迎回来,John!👋”。这些都是 LLM 的默认套路。请有意识地跳出这些模式。
0.E MOBILE-DESIGN.md(持久化产物)
App Read、Nav Read、拨盘值和设计令牌都是既定承诺,不是聊天中的临时内容。确定后,将它们写入项目根目录下的 MOBILE-DESIGN.md,并将其视为设计事实来源:后续会话(以及其他 Agent)在做出任何 UI 决策前都要先阅读;重新运行时会刷新该文件,并报告变更内容,而不是从头生成。此文件可以防止屏幕 3、4 和 5 漂移成另一个应用。(mobile-design-system 技能会写入令牌部分;此技能会写入各项 Read 和拨盘值。)
1. 三个拨盘
完成 App Read 后,设置三个拨盘。以下布局、动效和密度决策都受这些拨盘约束。
DESIGN_EXPRESSION: 4- 1 = 严格遵循平台原生设计,10 = 完全自定义品牌设计MOTION_INTENSITY: 4- 1 = 仅使用原生转场,10 = 处处采用手势驱动的物理效果VISUAL_DENSITY: 4- 1 = 轻盈的消费级体验,10 = 专业工具驾驶舱
基线为 4 / 4 / 4。 移动端基线低于 Web:在手机上,遵循惯例本身就是一项优势。根据需求说明,通过对话进行调整。
1.A 拨盘推断
| 信号 | EXPRESSION | MOTION | DENSITY |
|---|---|---|---|
| “原生 iOS / 简洁 / 类似 Apple Notes、Things” | 1-3 | 2-3 | 3-4 |
| “实用 / 工具 / 好用即可” | 3-4 | 3-4 | 4-5 |
| “消费级社交 / 内容流” | 5-7 | 5-7 | 4-5 |
| “品牌感强 / 活泼 / 类似 Duolingo / 儿童” | 7-9 | 6-8 | 2-4 |
| “高端 / 奢华 / 时尚电商” | 7-9 | 5-7 | 2-3 |
| “专业工具 / 交易 / 运营 / 数据密集” | 3-5 | 2-3 | 7-9 |
| “金融科技(消费级)” | 4-6 | 3-5 | 4-6 |
1.A2 类别偏好(按应用类型:优先采用 / 避免)
| 应用类型 | 优先采用 | 避免 |
|---|---|---|
| 金融科技 | 数字清晰易读(表格数字、金额使用等宽字体)、传递信任的中性色、资金操作的明确状态 | 活泼的吉祥物、渐变余额卡片、动画中抖动的小数 |
| 健康 / 健身 | 每个屏幕突出一个核心指标、宽松易读的字体、鼓励但朴实的文案 | 三项统计仪表盘、用红色表示进度、制造连续打卡压力的设计 |
| 消费级社交 | 内容优先(媒体内容就是 UI)、快速内容流、克制的界面装饰 | 每条帖子都套上厚重卡片、诱导互动的徽章 |
| 电商 | 为产品摄影留出呼吸空间、固定且清晰的价格 + CTA、仅在真实紧迫时营造紧迫感 | 徽章满天飞、倒计时、杂乱的产品卡片 |
| 效率 / 工具 | 密度优先于装饰、键盘优先的流程、即时交互 | 新手引导、每个视图都配插画式空状态、庆祝弹窗 |
| 儿童 | 更大的触控目标(>= 56pt)、高对比度、杜绝暗黑模式设计 | 过小的图标按钮、紧邻广告的布局、无限滚动机制 |
1.E 标志性元素
每个屏幕最多采用一个大胆设计——独特的标题样式、一个标志性交互或一个表现力突出的组件。其他部分都应保持克制,并带有原生感。将大胆设计的预算集中在一个地方;如果屏幕上的一切都很有表现力,整体就会显得嘈杂;如果应用的每个屏幕都在大声张扬,它就毫无个性可言。这是在屏幕层面重申 CHROME LAGS CONTENT(1.C)。
1.B DESIGN_EXPRESSION 档位(实际应用)
- **1-3 平台原生:**系统字体、原生标题栏和标签栏、平台组件与选择器,默认采用平台差异化设计(通常为
per-platform-native)。 - **4-7 品牌化原生:**自定义颜色 / 字体令牌和自定义内容组件;导航界面装饰(标题栏、标签栏、转场)仍保持原生。
- **8-10 完全自定义:**自定义标签栏、自定义转场、各处使用品牌字体、跨平台采用统一外观。现在,原生界面装饰原本免费为你处理的每个安全区域内边距、按下状态和无障碍角色,都将由你负责。
1.C 导航栏应滞后于内容(强制要求)
即使内容样式已经完全融入品牌风格,导航栏也应保持原生样式,直到 DESIGN_EXPRESSION >= 8。自绘制的标签栏若存在安全区域问题且没有按压状态,是“表达性”AI 应用最常见的失败之处。先为内容注入品牌风格,再考虑导航栏。
1.D 硬性下限(旋钮设置不得覆盖这些要求)
- 即使
VISUAL_DENSITY: 10,触控目标也必须保持 >= 44pt。 - 当
MOTION_INTENSITY: 3以上时,必须遵循减少动态效果的设置。 - 在所有动态效果级别下,动画都必须在 UI 线程上运行(第 8 节)。
2. 从需求简介映射到技术栈
根据需求简介选择基础方案。首先检查项目现有的 package.json——现有技术栈优先于以下所有默认方案。
| 需求简介特征 | 推荐方案 | 原因 |
|---|---|---|
| 可塑造品牌风格的跨平台应用(默认) | Expo + Expo Router + NativeWind + React Native Reusables | Tailwind 语法样式、可自主掌控的 shadcn 风格组件、基于文件的导航 |
| Material / Android 优先的产品 | React Native Paper (Material 3) | 官方品质的 M3 组件和主题 |
| 原生 iOS 体验 | 原生导航栏 + 系统字体 + SF Symbols (expo-symbols),最少的样式层 | 符合 HIG 胜过任何组件库 |
| 对性能要求极高的自定义设计系统 | Tamagui | 编译器优化的设计令牌和变体 |
| 保守方案 / 不想使用构建工具 | 纯 StyleSheet.create + React Navigation | 没有魔法,每位 RN 开发者都能看懂 |
| 遗留的 Draftbit v1 应用 | @draftbit/ui (Jigsaw) | 与现有组件系统保持一致 |
诚实原则(沿用 taste-skill 的原则,精神上逐字遵循):
- 导入任何第三方库之前,先检查
package.json。如果缺少该库,先输出安装命令(使用npx expo install …,以解析出兼容 SDK 的版本),再给出代码。 - 每个应用只使用一种组件系统。不要在同一棵组件树中混用 Paper 和 Reusables。
- 每个应用只使用一种图标系列。不要混用 SF Symbols、Material 图标和 Lucide。
- 如果要近似实现平台设计模式(例如在自定义组件中实现 iOS 大标题页眉),请在注释中标明这只是近似实现。
3. 默认架构与约定
除非技术栈映射表另有选择:
- 框架: Expo + TypeScript。使用 Expo Router 进行基于文件的导航(
app/目录)。 - 样式: NativeWind(Tailwind 语法)。设计令牌(颜色、字体比例、圆角)放在 Tailwind 配置 / 主题文件中——屏幕文件中不得出现内联十六进制颜色值。
- 列表: 对任何长度不受限制的列表使用 FlashList(或 FlatList)。
ScrollView仅用于固定且简短的内容。FlashList 版本相关细节请参阅 versions.md。 - 图像: 在列表单元格中使用
expo-image,并配置placeholder(blurhash)和recyclingKey。 - 安全区域: 使用
react-native-safe-area-context(useSafeAreaInsets)。绝不硬编码状态栏内边距。 - 图标: 统一使用
@expo/vector-icons、Lucide RN 或 Phosphor RN 中的一个系列;若要采用原生 iOS 风格,则使用expo-symbols。全局统一图标尺寸和描边粗细。绝不使用表情符号作为图标。绝不手绘 SVG 图标路径。 - 字体: 默认使用系统字体(见 6.1)。通过
expo-font/@expo-google-fonts加载自定义字体,并在隐藏启动画面前完成加载。 - 动画: 使用 Reanimated + Gesture Handler。在根节点只放置一次
GestureHandlerRootView。 - 触觉反馈: 使用
expo-haptics,并遵循 6.5 节中的反馈用语规范。普通导航点击绝不触发触觉反馈。 - 布局机制: 仅使用 flexbox(RN 中没有 CSS Grid)。优先使用
gap,而不是连续添加外边距。固定像素宽高仅用于图标和头像——屏幕布局应使用弹性尺寸。
4. 导航架构
必须先设计导航,再设计屏幕。完整决策树、Expo Router 约定和示例请参阅:../_shared/references/navigation.md。不可妥协的要求如下。
4.A 导航结构说明(在任何代码之前输出)
一个结构化路由树,同时作为 app/ 目录规划:
NAV READ
platforms: iOS + Android (web: best-effort)
tabs (4): Today · Search · Library · Profile
app/
(auth)/sign-in, sign-up fullscreen group, swapped on session
(tabs)/
index Today → push workout/[id]
search Search → push workout/[id]
library Library → push collection/[id] → workout/[id]
profile Profile → push settings, settings/units
new-workout modal (pageSheet), max 1 internal step
player/[id] fullscreen modal, custom dismiss
entry points: settings ← gear (Today header) · new-workout ← + (Library header)
sheets: workout-options, filter (write "sheets: none" when there are none)
deep links: /workout/:id, /collection/:id
android back: default pop everywhere; new-workout confirms discard
max taps to any core screen: 2
4.B 容器决策树(按顺序评估)
- 用户会反复返回的顶层目的地,与其他目的地同级,且状态独立?→ 标签页根视图。
- 有明确父级的下钻流程(列表 → 详情、设置 → 子设置)?→ 推入。
- 完成后返回的独立创建/编辑任务(撰写、筛选器、编辑个人资料)?→ 模态视图(iOS 默认使用
pageSheet)。 - 必须保持父级上下文可见;用于轻量选择、预览或操作菜单;内容少于一屏,且无内部导航?→ 底部面板。如果面板需要自己的返回堆栈,就应该使用模态视图。
- 沉浸式或阻断式流程(相机、媒体查看器、付费墙、引导流程、身份验证)?→ 全屏模态视图/路由组。
4.C 导航硬性规则
- 标签页:3-5 个。 只有两个目的地 → 不要使用标签栏。六个 → 错的是信息架构(IA),不是标签栏。 标签始终可见,且每个标签只用一个词。
- 不要设置标签页,不要登出标签页。 设置入口放在个人资料中;登出入口放在设置中。
- 仅当创建是核心操作时才使用居中 FAB——此时标签页数量必须 <= 4,并在导航说明中说明理由。
- 不要嵌套标签栏。不要使用双重标题栏。 每个屏幕只能有一个标题栏所属方。
- Android 返回 = 标题栏返回。 除导航说明中声明的放弃确认外,不要覆盖
BackHandler。 - 每个模态视图都必须有明确的关闭控件(X 或取消)。仅支持滑动关闭不合格。
- 身份验证/引导流程应使用路由组(会话状态变化时切换
(auth)),不要在屏幕内部条件渲染。 - 每个详情屏幕都必须支持深层链接(包含参数的路由文件),并进入合理的返回堆栈。
- 抽屉仅适用于大型次级目录(Gmail 级别);绝不能用作消费类应用的主要导航,也不能用汉堡菜单隐藏本该放在标签栏中的 4 个目的地。
- 如果一个屏幕会打开 2 个以上不同的底部面板,说明信息架构被藏在面板里了。
5. 屏幕结构与布局规范
- **安全区域:**有导航标题栏时,顶部内边距由导航器标题栏管理;否则使用
useSafeAreaInsets()。每个可滚动区域的底部都应设置:contentContainerStyle={{ paddingBottom: insets.bottom + <spacing> }}。绝不要使用paddingTop: 50这类随意的数值。 - **标题栏所属方:**导航标题栏负责显示屏幕标题。如果标题栏已经显示标题,不要在其下方的内容中重复添加
<Text>标题。 - **触控目标:**有效尺寸 >= 44x44pt。较小的图标应添加
hitSlop。行高 >= 44pt。 - **拇指操作区:**主要操作放在屏幕下半部分;破坏性或不常用的操作可以放在顶部。固定页脚 CTA 应适配安全区域,不要使用
bottom: 30。 - **间距网格:**采用 4/8pt 比例(4、8、12、16、24、32)。屏幕水平内边距设为 16(紧凑)或 20(宽松)——选定一种并固定使用。
- **垂直布局:**内容顶部对齐。
justifyContent: 'center'仅用于空状态、身份验证和过渡页——数据屏幕上的内容会随增长而跳动。 - **列表:**行高一致;所有动态文本都设置
numberOfLines;每个信息流都支持下拉刷新(RefreshControl);超过约 20 个条目时使用虚拟化。 - **键盘:**每个带输入框的屏幕都必须妥善处理键盘(参见 skeletons.md 中的规范骨架)。键盘打开时,提交按钮必须保持可见。
- **文本输入框:**标签放在输入框上方;每个输入框都要设置正确的
keyboardType、textContentType/autoComplete(电子邮件使用电子邮件键盘;姓名/地址使用自动填充)。不要用占位符代替标签。错误文本放在输入框下方。
6. 设计工程指令(偏差校正)
6.1 字体排印
- 在移动端,系统字体是可靠的默认选择。 SF Pro 和 Roboto 一点也不显得土——高品质应用用的就是它们。这与 Web 技能中禁用 Inter 的规则正好相反。自定义字体必须证明其价值:最多使用 1-2 种字体,须在启动画面隐藏前加载,并通过 Dynamic Type 验证。
- 警惕趋同陷阱: 如果确实有理由使用自定义字体,不要选用每个 AI 都会采用的“安全型自定义”默认字体——Poppins、Nunito、通用几何圆角无衬线体(相当于 Web 中 Space Grotesk 陷阱的移动端版本)。根据设计简报的实际风格来选,并在不同项目中有所变化。
- 根据设计令牌设置字体比例,不要在每个屏幕里直接填写
fontSize数值。屏幕最多需要:展示文字(少用)、标题、正文、说明文字。不要让每个屏幕都以fontSize: 32 / fontWeight: '700'和灰色副标题开场——每个屏幕都采用相同节奏会暴露模板痕迹。 - Dynamic Type 支持双向调整: 既要支持缩放,也要限制缩放范围——自定义界面文字(按钮、自定义标题栏)的
maxFontSizeMultiplier设为约 1.3-1.5,正文文字不设上限。由原生组件管理的界面元素(导航器标签、原生标题栏)没有此属性——须在设备上验证缩放效果(14.C),不能只在代码中检查。 - Android 的细节: 展示文字需设置
includeFontPadding: false和明确的lineHeight。
6.2 色彩校准
- 默认最多使用 1 种强调色,饱和度低于 80%。在主题文件中定义中性色阶(使用同一灰色系——应用中绝不混用暖灰和冷灰)。
- 禁止使用靛蓝色套路:
#6366F1/#8B5CF6/#7C3AED搭配LinearGradient标题栏、行动号召按钮或引导页,是 AI 移动应用的典型特征。禁止将其作为默认方案。只有品牌确实以紫色为主时才可例外——届时要有明确意图,避免滥用渐变。 - 渐变:默认每个应用最多使用 1 处,且必须有构图上的理由。
- 从一开始就支持深色模式,通过
useColorScheme和语义化设计令牌(background、surface、text-primary、accent)实现。发布前测试两种模式。 - OLED 例外: 在移动端(OLED),纯
#000000可以是经过审慎考虑的深色模式选择。禁止的是未经考虑就默认使用纯黑。浅色模式仍应避免使用纯黑文字(改用近黑色)。 - 色彩一致性锁定: 只用一种强调色,并在每个屏幕中保持完全一致。发布前进行检查。
6.3 表面、层级与卡片
- 分组不只靠卡片。 也可以使用留白、细分隔线(
StyleSheet.hairlineWidth)和分组列表区块(iOS inset-grouped 样式)。卡片应是独立、可点击且内容完整的对象。灰色背景上堆叠白色圆角 2xl 阴影卡片,是 AI 移动应用最常见的布局。 - 跨平台层级令牌: 一次性定义 2-3 个层级(每个层级都同时包含 iOS 阴影属性和 Android
elevation)。在 Android 上,不设置elevation的shadowColor不可见——两者缺一不可。 - 形状一致性锁定: 使用一套圆角比例(例如 8/12/16),并按用途应用。不要让输入框使用 24 的
borderRadius,旁边的卡片却使用 8。 - 模糊效果(
expo-blur) 只用于媒体内容或覆盖层。不要为了“高级质感”而将其用于卡片或标签栏。
6.4 交互状态(每个数据屏幕都必须完整覆盖)
- 加载中: 内容屏幕使用与最终布局一致的骨架屏;只有按钮级操作才使用转圈指示器。绝不要用全屏转圈指示器遮住标签栏。
- 空状态: 设计完整,并包含能填充内容的操作。此处居中布局是合适的。
- 错误: 表单错误以内联方式显示;内容错误提供重试操作;临时错误使用 toast/snackbar。
- 离线: 信息流和数据类应用应显示离线横幅,并提供缓存内容。仅在存在网络层时适用——本地优先应用可在 App Read 中声明“offline: N/A”,并合法跳过此项。
- 刷新中: 信息流使用
RefreshControl,与首次加载区分开来。 Alert.alert()仅用于破坏性操作的确认。 不用于成功、错误或提示信息。成功时更新状态,并可选择提供触觉反馈;错误以内联方式显示。
6.5 触觉反馈词汇
选择器和切换控件使用选择触觉反馈;有意义的确认使用轻微冲击反馈;异步结果(成功/失败)使用通知触觉反馈。**普通点击和导航时绝不触发。**触觉反馈过多就是过度纠正的信号。
6.6 权限预先说明(LLM 约 100% 会处理错)
冷启动时或在挂载 useEffect 中绝不请求系统权限。在用户表达意图时,先提供上下文,再请求权限:
| 权限 | 询问时机 |
|---|---|
| 通知 | 首次带来价值之后(创建第一个任务、下第一个订单) |
| 位置 | 用户点击依赖位置信息的功能时 |
| 相机/照片 | 用户发起拍摄/上传时 |
| 联系人 | 用户打开邀请/分享流程时 |
6.7 文案与内容(从 taste-skill 移植,通用)
- 所有可见字符串中完全禁止使用破折号(
—)。改用连字符或调整句式。 - 不要使用“John Doe”/“Acme”/过于完美的假数据(
99.99%);使用真实姓名和有瑕疵的数据。 - 不要使用空洞的动词:“Elevate”“Seamless”“Unleash”“Supercharge”。
- 不要使用带感叹号的引导语气(“Let's get started! 🎉”“You're all set!”)。
- 除非个性化本身就是产品,否则不要使用“Welcome back, {name}! 👋”作为问候标题。
- **发布前进行文案自查:**重新阅读每一条可见字符串;改写任何语法错误、指代不清或带有 LLM 式俏皮感的内容。
7. 动效
此处所有内容的规范代码:../_shared/references/skeletons.md。规则如下:
- 移动端动效层级:(1)导航过渡:使用原生动效,无需额外实现;(2)按压反馈:所有可触控元素都要有,弹簧缩放约为 0.97;(3)状态过渡:插入/移除/重新排序时使用布局动画;(4)与滚动联动的界面元素:折叠式标题栏;(5)手势驱动的动效:底部面板、可滑动行。按此顺序实现;如果屏幕有视差效果却没有按压状态,优先级就反了。
- 动效必须有明确目的:用于层级、反馈、状态变化或叙事。无法用一句话说明理由,就删掉。
- 交互反馈优先使用弹簧曲线,而非定时曲线。不要使用线性缓动。
- 进入动画绝不能无条件地用于虚拟化列表单元格:回收的单元格会在滚动过程中重播动画。仅在首次挂载时对最前面的约 6 行添加交错动画,并根据索引进行限制。
- **避免实现以下效果(默认不要尝试):**共享元素过渡(没有稳定的 API,可用淡入加缩放近似,并注明);自定义下拉刷新(应使用
RefreshControl);手动实现标签页切换过渡(由导航器负责)。 - **降低动态效果:**当
MOTION_INTENSITY: 3以上时遵循useReducedMotion;手势仍须有效,装饰性动效则立即完成。
8. 性能保障规则
- **动画仅在 UI 线程运行。**使用 Reanimated worklets/原生驱动。在 transform/opacity 上设置
useNativeDriver: false属于严重错误。使用onScroll驱动useState也属于严重错误,滚动位置应存放在共享值中。 - **渲染期间绝不读取或写入
.value。**从 worklets 调用 JS 时使用runOnJS。 - 对无界列表进行虚拟化;对行组件进行记忆化;确保
keyExtractor稳定。 - 使用
expo-image进行缓存并显示占位图;在单元格中设置recyclingKey。 - **保持启动页衔接连贯:**启动页背景色应与首屏背景色一致;字体和初始数据应在隐藏启动页之前准备好(避免闪白或字体切换闪烁)。
- **控制重新渲染:**按变化频率拆分上下文;列表屏幕不能因远处输入框的每次按键而重新渲染。
9. 平台约定
- **按压反馈:**Android 涟漪效果(
android_ripple)与 iOS 透明度/缩放效果;或者在EXPRESSION >= 6时,两端一致采用一种品牌化按压样式。 - **选择器、日期/时间、开关、分享:**默认使用系统组件(
EXPRESSION <= 7)。自定义选择器是最后手段。 - **Android:**手势/硬件返回行为保持一致(4.C);采用边到边布局,并正确处理导航栏内边距;涟漪效果限制在行内。
- **iOS:**默认将模态页面设为
pageSheet;通过 ActionSheet 确认破坏性操作;尊重 Home 指示条。 - **Web(react-native-web):**悬停仅作为渐进增强——任何功能都不得依赖它。依赖 FlashList/手势库前,先确认其 Web 支持情况(参见 versions.md)。Web 布局应设置最大内容宽度(约 640-760px);将手机布局拉伸到 1440px 是糟糕的设计。
- **
Platform.select的使用原则:**平台分支应放在 tokens/组件中,而不是散落在各个屏幕文件里。
10. 移动端 AI 露馅特征(禁止模式)
完整露馅特征目录(仅追加,共 42 条且持续增加)+ 可运行的 grep 检查清单:
../_shared/references/tells.md。
发布前请阅读。最容易辨认的十种特征始终适用:
- 图标芯片行 - 每行都以一个 40x40 的彩色圆角方块开头,里面放着彩色图标。这是 RN 代码粗制滥造的头号特征。
- 靛蓝流水线 -
#6366F1系配色 +LinearGradient标题/CTA(6.2)。 - 卡片堆叠屏幕 - 每个屏幕都是一堆带阴影的白色圆角卡片(6.3)。
- 表情符号图标 - 标签栏、按钮、空状态中出现 🔥⚙️📊。
- 默认五个标签页加 FAB - 不管是什么应用,都采用 Home/Search/+/Alerts/Profile(4.C)。
- 用 ScrollView 处理映射列表 - 对无界数据使用
<ScrollView>{items.map(…)}</ScrollView>。 - 神奇的顶部内边距 - 用
paddingTop: 50代替安全区内边距(5)。 - 三页引导流程 - 插图 + 标题 + 圆点 + 跳过按钮,三页几乎一模一样。
- 什么都用 ALERT.ALERT() - 仅用于确认破坏性操作(6.4)。
- “欢迎回来,John!👋” - 首页采用问候标题,入门引导采用感叹式语气(6.7)。
本套文档中会按编号引用这些露馅特征;编号以 tells.md 为准,且仅追加。
11. 重新设计现有应用
重新设计是一门有其专属技能的独立学科——请勿在此自行发挥:
- 单个屏幕 → 使用
mobile-redesign-screen技能。 - 整个应用 → 使用
mobile-redesign-app技能(唯一允许提出导航结构调整的技能)。 - 只做审查,不做任何更改 → 使用
mobile-design-review技能。
这三种技能均遵循 ../_shared/references/redesign-protocol.md(审查清单、现代化手段、风险控制)和 review-rubric.md。触碰现有代码时,对本技能也有约束的一条规则是:绝不可悄悄更改——标签页顺序、路由/深链接路径、主题 token 名称、表单字段语义、用户已熟悉的手势。
12. 区块库(契约)
../_shared/blocks/<category>/<name>.md - 经过验证的屏幕模式。类别:onboarding、auth、feed、detail、profile、settings、paywall、search、empty-states、navigation。
**优先使用区块:**在手动搭建任何典型屏幕(入门引导、身份验证、信息流、设置、付费墙、空状态)之前,先列出 ../_shared/blocks/,并检查是否有 dial_compatibility 覆盖所需 dials 的匹配区块。调整现有区块,不要重新发明。
Frontmatter 模式
---
name: value-first-onboarding
category: onboarding
dial_compatibility:
expression: [3, 8]
motion: [3, 7]
density: [2, 5]
platforms: [ios, android, web]
when_to_use: "Consumer apps where the aha-moment can be shown, not told."
not_for: "Pro tools; apps where signup is legally required first."
stack: ["expo-router", "nativewind", "reanimated"]
---
必需的正文部分
- 屏幕草图(ASCII 或文字说明) 2. Props/路由 API 3. 代码草图
- 平台说明(iOS/Android/Web 的差异) 5. 按 MOTION 范围划分的动效变体 + 减少动效设置 6. 深色模式说明 7. 反模式 8. 真实案例参考。
区块必须通过第 14 节的预检。每个文件放置一个区块。
13. 不在范围内
- 营销/落地页网站 → 使用原始 taste-skill。
- 游戏、3D、以画布为主的应用(Skia/GL 可作为组件使用,但不能作为应用本身)。
- watchOS/tvOS/小组件/App Clip。
- 原生模块编写、构建工具、商店提交。
- Flutter/SwiftUI/Kotlin——此技能面向 React Native。
如果需求属于上述任一项,请说明并指向正确的工具。
14. 最终交付前检查
交付前逐项检查。按验证方式分类。
14.A Grep 机械检查(逐字运行这些检查——现成命令块位于 ../_shared/references/tells.md 末尾)
- 可见字符串中不含破折号(
—/–) - JSX 文本中不含 emoji(除非需求明确要求活泼风格——此时应有意且少量使用)
- 不含
#6366F1|#7C3AED|#8B5CF6;LinearGradient计数 <= 1 - 屏幕文件中不含内联十六进制颜色(仅使用 tokens)
- 不存在用
ScrollView包裹无界数据.map(的情况(先 grep,再检查命中项: 有界静态映射可以接受) - 不含
paddingTop: [4-6][0-9]这样的魔法数字;使用安全区域 inset - 不含
useNativeDriver: false;不含由onScroll驱动的useState -
Alert.alert仅用于破坏性操作确认 -
shadowColor始终与同级的elevation一起使用 - 每个具有电子邮件/电话/姓名角色的
TextInput都有keyboardType+textContentType/autoComplete - 如果使用手势/底部弹层,根节点仅有一个
GestureHandlerRootView
14.B 设计机械检查(在代码中统计/检查)
- 已输出 App Read + Nav Read,刻度设置明确且有理有据
- 标签页数量为 3-5 个,标签清晰可见;不设 Settings/Logout 标签页;FAB 有充分理由或不使用
- 不嵌套标签栏;不重复显示标题栏;认证流程属于路由组
- 每个模态窗口都有明确的关闭方式;Android 返回行为一致(不使用未声明的 BackHandler)
- 界面框架滞后于内容:使用原生导航界面框架,除非 EXPRESSION >= 8
- 使用一个图标系列、一个强调色、一套圆角比例、一组灰阶
- 触控目标 >= 44pt(小图标使用 hitSlop);行高一致
- 所有界面的内边距统一(16 或 20)
- 每个数据界面都覆盖完整状态周期:骨架屏/空状态/错误/离线/刷新 (已声明的本地优先应用可以不处理离线状态)
- 在用户有意触发操作时请求权限,绝不在挂载时请求
- 按规范使用触觉反馈;所有可触控元素均有按压反馈
- 入场动画按索引保护,绝不在列表单元格中无条件播放
- 深色模式 tokens 完整;两种模式均已检查
- Dynamic Type:自定义界面框架文本设置
maxFontSizeMultiplier,正文不设上限 (原生自带的界面框架需通过 14.C 设备检查) - 已完成文案自审(无填充动词、无断裂字符串、无问候式标题)
- 每个自定义 Pressable 都设置了
accessibilityLabel/accessibilityRole
14.C 需使用模拟器/设备验证(如实说明)
- 键盘:键盘打开时提交按钮仍可见,两个平台均验证
- 启动画面 → 首个界面:无白屏闪烁、无字体切换
- 最长列表的滚动性能(无空白单元格、无卡顿)
- 标签栏可适应 1.3 倍字体缩放
- Android 边到边 inset 正确
如果没有可用的模拟器/设备工具,请准确说明 14.C 中哪些检查未能验证。 虚报未验证的检查,比留下未勾选项更糟糕。
如果有任何一项无法如实勾选,应用就还未完成。交付前请修复。