# 项目约定 ## 视觉设计 - 采用 Flat Design 风格:无阴影、无卡片嵌套、扁平化 - 主色:`#10B981`(Tailwind 祖母绿) - 图标灰:`#6B7280`(gray-500),无彩色背景 - 文本灰:`#374151`(gray-700) - 辅助灰:`#9CA3AF`(gray-400) - 分割线灰:`#E5E7EB`(gray-200) ## 交互 - 所有 loading 统一用 sonner-native(不再使用按钮级 loading) - 使用 `@/hooks/useLoading` + `LoadingOverlay` 组件 ## 组件规范 - 不要卡片套卡片(no card nesting) - 子应用 icon 不设彩色背景 - Section 标题统一用 `SectionLabel` 组件(13px semibold text-gray-800) ## 已知库问题 - **BottomSheet 初始化闪烁**:gorhom bottom-sheet 默认 `animateOnMount=true`,即使 `index=-1`(关闭状态)mount 时也会触发动画,首帧显示底部面板。修复:``。**不要用 `{isOpen && }` 条件渲染**,会导致 `BottomSheetContentContainer` 的 `useRef(isOpen)` 捕获错误初始值,首次打开时 `snapToIndex` 永远不会触发。 - **模板字面量 `id` 解析错误**:Expo/Babel 在 `.tsx` 文件中会把模板字面量内的 `id,` 误解析为 JSX 属性,报 `Missing semicolon`。**规则:`.tsx` 文件中禁止在模板字面量(反引号)内使用 `id` 关键字**,必须改用字符串拼接(`'...' + '...'`)。仅提取为变量不够,必须完全避免模板字面量。 - **BottomSheet 内 input 键盘避让**:三层根因,缺一不可: 1. `keyboardBehavior` 必须是 `"interactive"`(gorhom 默认值),不能用 `"extend"`。gorhom 源码:`extend` 只拉到最高 snap point 不上移;`interactive` 才会 `highestDetent - keyboardHeight` 上移避让。 2. `android_keyboardInputMode` 必须是 `"adjustPan"`(gorhom 默认值),不能用 `"adjustResize"`。源码 L605:Android + adjustResize 会**跳过** interactive 模式。 3. sheet 内输入框必须接入 sheet 的键盘状态。最优方案:用 heroui 原生 `Input` + `useBottomSheetAwareHandlers`(从 `heroui-native` 导出),hook 内部调用 gorhom `useBottomSheetInternal(true)` 把 focus/blur 注册到 `animatedKeyboardState`。项目已封装为 `BottomSheet.Input`。 **规则:BottomSheet 内部的所有输入框统一用 `BottomSheet.Input`,`BottomSheet.tsx` 中 `keyboardBehavior="interactive"` + `android_keyboardInputMode="adjustPan"` 保持 gorhom 默认值。**