# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## user rools 每次开头请叫我哥哥 请严格遵守ui设计规范,使用响应式布局设计,不要硬编码 请使用项目里面封装好的ui组件,如果没有请提醒我 ## Project Overview React Native + Expo mobile application built on **Ignite CLI boilerplate** (v11.4.0). Uses TypeScript, React Navigation 7, and NativeWind (Tailwind CSS). ## Common Commands ```bash pnpm install # Install dependencies pnpm run start # Start Expo dev client pnpm run android # Run on Android (expo run:android) pnpm run ios # Run on iOS (expo run:ios) pnpm run compile # TypeScript type check (tsc --noEmit) pnpm run lint # ESLint with auto-fix pnpm run lint:check # ESLint without fix pnpm run test # Run Jest tests pnpm run test:watch # Run Jest in watch mode # EAS Builds (requires expo-cli) pnpm run build:ios:sim # iOS simulator build pnpm run build:android:sim # Android emulator build pnpm run prebuild:clean # Regenerate native projects ``` ## Architecture ### Directory Structure - `app/` - Main application source - `components/` - 12个基础 UI 组件(详见下方组件列表) - `screens/` - Screen components connected to navigation - `screens/DemoShowroomScreen/demos/` - 组件演示页面(展示组件用法,非实际组件) - `navigators/` - React Navigation configuration (AppNavigator, DemoNavigator) - `context/` - React Context providers (AuthContext, ThemeContext, ToastContext) - `services/api/` - API layer using Apisauce (`authApi.ts` for auth, `index.ts` for base API) - `theme/` - Design tokens (colors, spacing, typography) and theme system - `i18n/` - Internationalization with i18next (8 languages: en, zh, ar, es, fr, hi, ja, ko) - `utils/` - Utilities including MMKV storage wrapper - `config/` - Environment-based configuration (dev/prod) - `devtools/` - Reactotron configuration ### Key Patterns **State Management**: React Context + MMKV for persistence. No Redux. **Theming**: Use `useAppTheme()` hook and `ThemedStyle` pattern: ```typescript const $container: ThemedStyle = ({ colors, spacing }) => ({ backgroundColor: colors.background, padding: spacing.lg, }) ``` **Navigation**: Two-layer structure - AppStack (auth/main screens) and DemoNavigator (bottom tabs). Type-safe routes defined in `navigationTypes.ts`. Auth screens: AuthWelcome, Login, Register, ForgotPassword. Main screens: Welcome, Profile, Settings, Security, Theme, Language, About, etc. **API Layer**: Singleton `Api` class in `services/api/index.ts` using Apisauce with typed responses. **Styling**: NativeWind (Tailwind CSS) configured. Use `className` prop for Tailwind styles. **Authentication**: `AuthContext` provides full auth flow with step-based state machines for login, register, and password reset. Supports email/password and Google Sign-In. Uses JWT tokens stored in MMKV. ## UI 设计规范 ### 参考文件 | 类型 | 文件路径 | 说明 | |------|----------|------| | **设计令牌** | `app/theme/colors.ts` | 颜色系统(浅色主题) | | | `app/theme/colorsDark.ts` | 颜色系统(深色主题) | | | `app/theme/spacing.ts` | 间距系统 | | | `app/theme/typography.ts` | 字体排版 | | | `app/theme/styles.ts` | 全局样式($styles.container 等) | | **UI 参考页面** | `app/screens/DemoCommunityScreen.tsx` | **最佳参考** - 标准页面结构、ListItem 用法、Section 标题 | | | `app/screens/WelcomeScreen.tsx` | useHeader hook 用法 | | | `app/screens/ProfileScreen.tsx` | 设置页面、用户卡片 | | **组件演示** | `app/screens/DemoShowroomScreen/demos/` | 所有组件的用法示例(类似 Storybook) | ### 设计令牌 **颜色语义**(定义在 `app/theme/colors.ts`): ```typescript text: palette.neutral800 // 主要文本 textDim: palette.neutral600 // 次要文本 background: palette.neutral200 // 屏幕背景 border: palette.neutral400 // 边框 tint: palette.primary500 // 主色调(按钮、链接) separator: palette.neutral300 // 分隔线 error: palette.angry500 // 错误 ``` **间距系统**(`app/theme/spacing.ts`): ```typescript xxxs: 2, xxs: 4, xs: 8, sm: 12, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64 ``` **字体大小**(`app/components/Text.tsx`): ```typescript xxl: 36, xl: 24, lg: 20, md: 18, sm: 16(默认), xs: 14, xxs: 12 ``` ### Header 使用规范 **必须使用 `useHeader` hook**,不要直接在 Screen 内部放置 `
` 组件。 ```typescript // ✅ 正确写法 import { useHeader } from "@/utils/useHeader" useHeader({ title: translate("screenName:title"), leftIcon: "back", onLeftPress: () => navigation.goBack(), }, []) return ( {/* 内容 */} ) const $container: ThemedStyle = ({ spacing }) => ({ paddingTop: spacing.lg, // 覆盖 $styles.container 的 56px }) ``` **原因**: Header 组件默认添加顶部安全区域 padding,直接放在 Screen 内容中会导致 Header 上方出现额外空白。`useHeader` 通过 `navigation.setOptions()` 将 Header 设置为导航层的一部分。 ### 容器间距规范 `$styles.container`(定义在 `app/theme/styles.ts`): ```typescript container: { paddingTop: spacing.lg + spacing.xl, // = 56px(为无 Header 的 Tab 页面设计) paddingHorizontal: spacing.lg, // = 24px } ``` **使用 useHeader 的页面**需在 `$container` 中覆盖 paddingTop 为 `spacing.lg` (24px)。 **不要**在页面内容中再添加额外的 paddingTop 或 marginTop,避免重复间距。 ### ListItem 使用规范 **参考**: `app/screens/DemoCommunityScreen.tsx` **默认无分隔线**,保持简洁风格: ```typescript ``` 只有**连续列表项**需要视觉分隔时,才使用 `bottomSeparator`,且**最后一项不需要**: ```typescript ``` ### Section 标题规范 **参考**: `app/screens/DemoCommunityScreen.tsx` 的 `$sectionTitle` 样式 使用 `preset="subheading"` 作为 section 标题: ```typescript const $sectionTitle: ThemedStyle = ({ spacing }) => ({ marginTop: spacing.xxl, // 48px }) ``` ### 页面结构模板 **有 Header 的页面**(如设置、详情页): ```typescript import { useHeader } from "@/utils/useHeader" export const ExampleScreen: FC = ({ navigation }) => { const { themed } = useAppTheme() useHeader({ title: translate("exampleScreen:title"), leftIcon: "back", onLeftPress: () => navigation.goBack(), }, []) return ( {/* 内容 */} ) } const $container: ThemedStyle = ({ spacing }) => ({ paddingTop: spacing.lg, }) ``` **无 Header 的 Tab 页面**(参考 `DemoCommunityScreen.tsx`): ```typescript export const ExampleTabScreen: FC = () => { const { themed } = useAppTheme() return ( ) } const $title: ThemedStyle = ({ spacing }) => ({ marginBottom: spacing.sm, }) const $description: ThemedStyle = ({ spacing }) => ({ marginBottom: spacing.lg, }) const $sectionTitle: ThemedStyle = ({ spacing }) => ({ marginTop: spacing.xxl, }) ``` ### 组件列表 (`app/components/`) | 组件 | 用途 | |------|------| | `Screen.tsx` | 屏幕容器(SafeArea + 键盘适配 + 滚动) | | `Header.tsx` | 页面头部导航栏 | | `Card.tsx` | 卡片容器 | | `TextField.tsx` | 文本输入框 | | `Button.tsx` | 按钮(default/filled/reversed 预设) | | `EmptyState.tsx` | 空状态占位 | | `ListItem.tsx` | 列表项 | | `Icon.tsx` | 图标 | | `Text.tsx` | 文本(heading/subheading/bold 等预设) | | `AutoImage.tsx` | 自适应图片 | | `Toggle/` | 开关/复选框/单选框 | | `Avatar.tsx` | 用户头像(使用 expo-image 缓存) | | `Modal.tsx` | 模态框(bottom/center 预设) | | `Dialog.tsx` | 对话框(确认/提示) | **注意**: `screens/DemoShowroomScreen/demos/` 目录下的 `Demo*.tsx` 文件是组件**演示页面**,用于展示组件的各种用法和变体,类似 Storybook,不是实际组件。 ### 自适应布局 **Screen 组件预设**: - `preset="fixed"` - 固定布局,不可滚动 - `preset="scroll"` - 始终可滚动 - `preset="auto"` - 智能判断:内容超出屏幕时才启用滚动 **安全区域**: 使用 `useSafeAreaInsetsStyle` hook 处理刘海屏 ```typescript {/* 内容自动避开刘海和底部指示条 */} ``` **间距系统** (`app/theme/spacing.ts`): ```typescript xxxs: 2, xxs: 4, xs: 8, sm: 12, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64 ``` **字体大小** (`app/components/Text.tsx`) - 固定像素值,无响应式: ```typescript xxl: 36, xl: 24, lg: 20, md: 18, sm: 16(默认), xs: 14, xxs: 12 ``` ### Path Aliases - `@/*` → `app/*` - `@assets/*` → `assets/*` ## Import Restrictions (ESLint enforced) - Use `Text`, `Button`, `TextInput` from `@/components`, not from `react-native` - Use `SafeAreaView` from `react-native-safe-area-context`, not from `react-native` - Import named exports from `react` (not `import React from 'react'`) ## Testing Jest with Testing Library for React Native. Test files use `.test.ts(x)` suffix. Setup in `test/setup.ts`. Run single test: ```bash pnpm run test -- --testPathPattern="storage" ``` ## Web Support This app runs on web via Expo. Use `pnpm run start` and press `w` to open web. Note: React Navigation's `headerRight` may not work reliably on web - consider placing header elements directly inside Screen components if targeting web. ## Running on Physical Devices