Files
RN_Template/RN_TEMPLATE/CLAUDE.md
2026-02-05 13:16:05 +08:00

10 KiB
Raw Permalink Blame History

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

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<T> pattern:

const $container: ThemedStyle<ViewStyle> = ({ 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:

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:

xxxs: 2, xxs: 4, xs: 8, sm: 12, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64

字体大小app/components/Text.tsx:

xxl: 36, xl: 24, lg: 20, md: 18, sm: 16(默认), xs: 14, xxs: 12

Header 使用规范

必须使用 useHeader hook,不要直接在 Screen 内部放置 <Header> 组件。

// ✅ 正确写法
import { useHeader } from "@/utils/useHeader"

useHeader({
  title: translate("screenName:title"),
  leftIcon: "back",
  onLeftPress: () => navigation.goBack(),
}, [])

return (
  <Screen safeAreaEdges={["bottom"]} contentContainerStyle={[$styles.container, themed($container)]}>
    {/* 内容 */}
  </Screen>
)

const $container: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingTop: spacing.lg, // 覆盖 $styles.container 的 56px
})

原因: Header 组件默认添加顶部安全区域 padding直接放在 Screen 内容中会导致 Header 上方出现额外空白。useHeader 通过 navigation.setOptions() 将 Header 设置为导航层的一部分。

容器间距规范

$styles.container(定义在 app/theme/styles.ts:

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

默认无分隔线,保持简洁风格:

<ListItem
  tx="setting:option1"
  leftIcon="settings"
  rightIcon="caretRight"
  onPress={handlePress}
/>

只有连续列表项需要视觉分隔时,才使用 bottomSeparator,且最后一项不需要:

<ListItem text="Item 1" bottomSeparator />
<ListItem text="Item 2" bottomSeparator />
<ListItem text="Item 3" />

Section 标题规范

参考: app/screens/DemoCommunityScreen.tsx$sectionTitle 样式

使用 preset="subheading" 作为 section 标题:

<Text preset="subheading" tx="section:title" style={themed($sectionTitle)} />

const $sectionTitle: ThemedStyle<TextStyle> = ({ spacing }) => ({
  marginTop: spacing.xxl,  // 48px
})

页面结构模板

有 Header 的页面(如设置、详情页):

import { useHeader } from "@/utils/useHeader"

export const ExampleScreen: FC<Props> = ({ navigation }) => {
  const { themed } = useAppTheme()

  useHeader({
    title: translate("exampleScreen:title"),
    leftIcon: "back",
    onLeftPress: () => navigation.goBack(),
  }, [])

  return (
    <Screen
      preset="scroll"
      safeAreaEdges={["bottom"]}
      contentContainerStyle={[$styles.container, themed($container)]}
    >
      {/* 内容 */}
    </Screen>
  )
}

const $container: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingTop: spacing.lg,
})

无 Header 的 Tab 页面(参考 DemoCommunityScreen.tsx:

export const ExampleTabScreen: FC<Props> = () => {
  const { themed } = useAppTheme()

  return (
    <Screen preset="scroll" contentContainerStyle={$styles.container}>
      <Text preset="heading" tx="screen:title" style={themed($title)} />
      <Text tx="screen:description" style={themed($description)} />

      <Text preset="subheading" tx="screen:section1" style={themed($sectionTitle)} />
      <ListItem ... />
      <ListItem ... />
    </Screen>
  )
}

const $title: ThemedStyle<TextStyle> = ({ spacing }) => ({
  marginBottom: spacing.sm,
})

const $description: ThemedStyle<TextStyle> = ({ spacing }) => ({
  marginBottom: spacing.lg,
})

const $sectionTitle: ThemedStyle<TextStyle> = ({ 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 处理刘海屏

<Screen safeAreaEdges={["top", "bottom"]}>
  {/* 内容自动避开刘海和底部指示条 */}
</Screen>

间距系统 (app/theme/spacing.ts):

xxxs: 2, xxs: 4, xs: 8, sm: 12, md: 16, lg: 24, xl: 32, xxl: 48, xxxl: 64

字体大小 (app/components/Text.tsx) - 固定像素值,无响应式:

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:

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