You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.9 KiB
6.9 KiB
React Native AI Context - shadcn/ui x NativeWind
React Native 应用的 AI 上下文指南,结合 shadcn/ui 设计理念和 NativeWind 工具类。
概述
这是 React Native 应用的 AI 开发上下文,使用 NativeWind (Tailwind CSS for React Native) 作为样式解决方案,遵循 shadcn/ui 的设计理念。
核心技术栈
基础框架
- Expo - React Native 开发框架
- NativeWind - Tailwind CSS for React Native
- React Native Reusables - UI 组件库
shadcn/ui 设计原则
- Open Code - 代码完全可定制
- Composition - 组件可组合
- Distribution - 易于分发和安装
- Beautiful Defaults - 美观的默认样式
- AI-Ready - 支持AI开发
安装
# 初始化 Expo 项目
npx create-expo-app myapp --template expo-template-blank-typescript
cd myapp
# 安装 NativeWind
npm install --save-dev tailwindcss
npm install nativewind
npm install -D @types/react-native
# 配置 NativeWind
npx tailwindcss init
配置
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./App.{js,jsx,ts,tsx}",
"./src/**/*.{js,jsx,ts,tsx}",
],
presets: [require("nativewind/preset")],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [],
}
nativewind-env.d.ts
/// <reference types="nativewind/types" />
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [['babel-preset-expo', { jsxImportSource: 'nativewind' }]],
plugins: [
'react-native-reanimated/plugin',
'nativewind/babel',
],
};
}
核心组件
Button 组件
import { Text, Pressable, PressableProps, ViewProps, TextProps } from 'react-native';
import { cn } from '@/lib/utils';
interface ButtonProps extends PressableProps {
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';
size?: 'default' | 'sm' | 'lg';
className?: string;
children: React.ReactNode;
}
const Button = React.forwardRef<Pressable, ButtonProps>(
({ className, variant = 'default', size = 'default', children, ...props }, ref) => {
const variants = {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
};
const sizes = {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
};
return (
<Pressable
ref={ref}
className={cn(
'rounded-md text-sm font-medium flex items-center justify-center',
variants[variant],
sizes[size],
className
)}
{...props}
>
<Text className="font-medium">{children}</Text>
</Pressable>
);
}
);
Card 组件
import { View, ViewProps, Text, TextProps } from 'react-native';
import { cn } from '@/lib/utils';
interface CardProps extends ViewProps {
className?: string;
}
const Card = React.forwardRef<View, CardProps>(({ className, ...props }, ref) => (
<View ref={ref} className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)} {...props} />
));
const CardHeader = React.forwardRef<View, ViewProps>(({ className, ...props }, ref) => (
<View ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
));
const CardTitle = React.forwardRef<Text, TextProps>(({ className, ...props }, ref) => (
<Text ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} />
));
const CardContent = React.forwardRef<View, ViewProps>(({ className, ...props }, ref) => (
<View ref={ref} className={cn("p-6 pt-0", className)} {...props} />
));
设计令牌
颜色系统
// 使用 CSS 变量定义颜色
// 在 tailwind.config.js 中配置
字体系统
// NativeWind 中的字体设置
// 使用 Tailwind 的字体工具类
text-sm // 小号文本
text-base // 基础文本
text-lg // 大号文本
font-medium // 中等字重
font-bold // 粗体
开发规范
组件结构
src/
├── components/
│ ├── ui/ # 基础 UI 组件
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ └── ...
│ └── features/ # 功能组件
├── lib/
│ └── utils.ts # 工具函数
├── hooks/ # 自定义 hooks
└── screens/ # 屏幕组件
命名约定
- 组件使用 PascalCase:
Button.tsx - 文件使用 kebab-case:
user-profile.tsx - 样式类使用 camelCase 或 Tailwind 工具类
与 React Web shadcn/ui 对应
| React Web | React Native |
|---|---|
<Button> |
<Pressable> with styling |
<Card> |
<View> with border and shadow |
<Input> |
<TextInput> with styling |
<Dialog> |
<Modal> or <Modal> from react-native-modal |
<Toast> |
Toast from react-native-toast-message |
<Avatar> |
<Image> with circular styling |
相关资源
- NativeWind 文档
- React Native Reusables - UI 组件库
- Expo 文档
- shadcn/ui - Web 版本参考
- shadcn/ui llms.txt - 参考
MCP 集成
使用 AI 工具:
npx shadcn@latest mcp
最佳实践
- 使用 NativeWind 进行样式管理
- 遵循 shadcn/ui 的组件设计原则
- 组件应该是可组合和可定制的
- 使用 TypeScript 保证类型安全
- 使用 Expo Router 进行导航