mcpField
M
mobile-taste

mobile-taste

github.com/draftbit设计与 UI992 次安装17 周前更新
代码仓库

关于 mobile-taste

mobile-taste 是一项用于构建跨平台 React Native 应用界面、导航和组件的技能。它要求先理解产品需求并检查现有技术栈,再作出设计与实现选择。

主要功能

  1. 01从需求推断应用定位
  2. 02检查现有项目技术栈
  3. 03先规划导航再设计界面
  4. 04设定表现、动效与信息密度
  5. 05将设计决策记录到 MOBILE-DESIGN.md
  6. 06按情境选用移动端设计指导

适用场景

  1. 01构建新移动应用的界面
  2. 02制定导航与组件方案
  3. 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 先读取这些信号
  1. 应用类型 - 消费级社交、实用工具、健身/健康、金融科技、电子商务、内容/媒体、生产力、儿童、现场/运营工具。
  2. 风格关键词 - “简洁”“活泼”“高端”“iOS 原生感”“像 Airbnb”“信息密集/专业”“平静”“品牌感强”。
  3. 用户提到的参考应用。在移动端,真实应用就如同参考网站之于 Web,是设计语言的参照。
  4. 受众与使用情境 - 在火车上单手操作、在沙发上双手操作,还是在现场戴手套操作。情境决定信息密度和目标尺寸,而不是你的个人偏好。
  5. 目标平台 - iOS / Android / Web,以及哪个平台是首要平台。
  6. 不易察觉的约束 - 优先考虑无障碍的用户、儿童(更大的目标尺寸,不使用暗黑模式设计)、受监管场景(金融科技/健康领域的信息披露模式)、重度离线使用。
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 拨盘推断
信号EXPRESSIONMOTIONDENSITY
“原生 iOS / 简洁 / 类似 Apple Notes、Things”1-32-33-4
“实用 / 工具 / 好用即可”3-43-44-5
“消费级社交 / 内容流”5-75-74-5
“品牌感强 / 活泼 / 类似 Duolingo / 儿童”7-96-82-4
“高端 / 奢华 / 时尚电商”7-95-72-3
“专业工具 / 交易 / 运营 / 数据密集”3-52-37-9
“金融科技(消费级)”4-63-54-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 ReusablesTailwind 语法样式、可自主掌控的 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 容器决策树(按顺序评估)
  1. 用户会反复返回的顶层目的地,与其他目的地同级,且状态独立?→ 标签页根视图。
  2. 有明确父级的下钻流程(列表 → 详情、设置 → 子设置)?→ 推入。
  3. 完成后返回的独立创建/编辑任务(撰写、筛选器、编辑个人资料)?→ 模态视图(iOS 默认使用 pageSheet)。
  4. 必须保持父级上下文可见;用于轻量选择、预览或操作菜单;内容少于一屏,且无内部导航?→ 底部面板。如果面板需要自己的返回堆栈,就应该使用模态视图。
  5. 沉浸式或阻断式流程(相机、媒体查看器、付费墙、引导流程、身份验证)?→ 全屏模态视图/路由组。
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。 发布前请阅读。最容易辨认的十种特征始终适用:

  1. 图标芯片行 - 每行都以一个 40x40 的彩色圆角方块开头,里面放着彩色图标。这是 RN 代码粗制滥造的头号特征。
  2. 靛蓝流水线 - #6366F1 系配色 + LinearGradient 标题/CTA(6.2)。
  3. 卡片堆叠屏幕 - 每个屏幕都是一堆带阴影的白色圆角卡片(6.3)。
  4. 表情符号图标 - 标签栏、按钮、空状态中出现 🔥⚙️📊。
  5. 默认五个标签页加 FAB - 不管是什么应用,都采用 Home/Search/+/Alerts/Profile(4.C)。
  6. 用 ScrollView 处理映射列表 - 对无界数据使用 <ScrollView>{items.map(…)}</ScrollView>。
  7. 神奇的顶部内边距 - 用 paddingTop: 50 代替安全区内边距(5)。
  8. 三页引导流程 - 插图 + 标题 + 圆点 + 跳过按钮,三页几乎一模一样。
  9. 什么都用 ALERT.ALERT() - 仅用于确认破坏性操作(6.4)。
  10. “欢迎回来,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"]
---
必需的正文部分
  1. 屏幕草图(ASCII 或文字说明) 2. Props/路由 API 3. 代码草图
  2. 平台说明(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 中哪些检查未能验证。 虚报未验证的检查,比留下未勾选项更糟糕。

如果有任何一项无法如实勾选,应用就还未完成。交付前请修复。

评论

支持 Markdown