# 小程序UI开发规范 (Tailwind CSS v4)
## 概述
本规范定义了基于Taro框架的小程序UI开发标准,采用Tailwind CSS v4原子化样式和Heroicons图标库,遵循shadcn/ui组件设计模式。
## 技术栈
- **Taro 4** - 跨端小程序框架
- **React 18** - 前端框架
- **Tailwind CSS v4** - 原子化CSS框架
- **@egoist/tailwindcss-icons** - 图标库集成
- **@weapp-tailwindcss/merge** - Tailwind类名合并工具(小程序版tailwind-merge)
- **clsx** - 条件样式类名管理
## 目录结构
```
mini/
├── src/
│ ├── components/
│ │ └── ui/ # UI组件库
│ │ ├── button.tsx
│ │ ├── input.tsx
│ │ ├── card.tsx
│ │ └── ...
│ ├── pages/
│ ├── utils/
│ └── app.css # Tailwind样式入口
├── tailwind.config.js # Tailwind配置
└── postcss.config.js # PostCSS配置
```
## 样式规范
### 1. Tailwind CSS v4 使用规范
#### 1.1 基础类名使用
```typescript
// ✅ 正确使用原子类
标题
// ❌ 避免使用内联样式
标题
```
#### 1.2 类名合并规范
```typescript
// ✅ 使用twMerge处理动态类名冲突
import { twMerge } from '@weapp-tailwindcss/merge'
// 处理静态和动态类名的冲突
按钮
// 处理多个条件类名的合并
复杂组件
// ❌ 避免手动拼接类名导致冲突
按钮
```
#### 1.2 响应式设计
```typescript
// 使用Tailwind的响应式前缀
```
#### 1.3 状态样式
```typescript
// 悬停和焦点状态
// 禁用状态
```
### 2. 图标使用规范
#### 2.1 图标
使用`@egoist/tailwindcss-icons`提供的图标类名:
"mdi", "lucide", "heroicons", "heroicons-outline", "heroicons-solid"
```typescript
// 基础用法
// 图标大小和颜色
// 图标变体
// solid - 实心图标
// outline - 轮廓图标
// mini - 迷你图标 (20x20)
// micro - 微型图标 (16x16)
```
#### 2.2 图标命名规则
```
i-heroicons-[图标名]-[大小]-[变体]
```
- 大小: 16 | 20 | 24
- 变体: solid | outline
### 3. UI组件规范
#### 3.1 组件文件结构
每个UI组件应包含:
```typescript
// mini/src/components/ui/button.tsx
import { Button as TaroButton, ButtonProps } from '@tarojs/components'
import { cn } from '@/utils/cn'
import { cva, type VariantProps } from 'class-variance-authority'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input 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',
link: 'underline-offset-4 hover:underline text-primary',
},
size: {
default: 'h-10 py-2 px-4',
sm: 'h-9 px-3 rounded-md',
lg: 'h-11 px-8 rounded-md',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
interface ButtonProps extends ButtonProps, VariantProps {}
export function Button({ className, variant, size, ...props }: ButtonProps) {
return (
)
}
```
#### 3.2 常用组件示例
**按钮组件 (Button)**
```typescript
// 使用示例
```
**卡片组件 (Card)**
```typescript
用户信息
用户详情内容
```
**输入框组件 (Input)**
```typescript
```
### 4. 页面布局规范
#### 4.1 页面容器
```typescript
// 主容器
{/* 页面内容 */}
// 卡片布局
{/* 卡片内容 */}
```
#### 4.2 响应式断点
- `sm`: 640px
- `md`: 768px
- `lg`: 1024px
- `xl`: 1280px
- `2xl`: 1536px
### 5. 主题配置
#### 5.1 颜色系统
```css
/* 在 app.css 中定义 */
:root {
--primary: 59 130 246;
--primary-foreground: 255 255 255;
--secondary: 107 114 128;
--secondary-foreground: 255 255 255;
--accent: 243 244 246;
--accent-foreground: 17 24 39;
--destructive: 239 68 68;
--destructive-foreground: 255 255 255;
--muted: 249 250 251;
--muted-foreground: 107 114 128;
--border: 229 231 235;
--input: 255 255 255;
--ring: 59 130 246;
--background: 255 255 255;
--foreground: 17 24 39;
}
```
#### 5.2 Tailwind配置
```javascript
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
primary: 'rgb(var(--primary))',
'primary-foreground': 'rgb(var(--primary-foreground))',
secondary: 'rgb(var(--secondary))',
'secondary-foreground': 'rgb(var(--secondary-foreground))',
accent: 'rgb(var(--accent))',
'accent-foreground': 'rgb(var(--accent-foreground))',
destructive: 'rgb(var(--destructive))',
'destructive-foreground': 'rgb(var(--destructive-foreground))',
muted: 'rgb(var(--muted))',
'muted-foreground': 'rgb(var(--muted-foreground))',
border: 'rgb(var(--border))',
input: 'rgb(var(--input))',
ring: 'rgb(var(--ring))',
background: 'rgb(var(--background))',
foreground: 'rgb(var(--foreground))',
},
},
},
plugins: [
require('@egoist/tailwindcss-icons')({
// 配置Heroicons
collections: {
heroicons: {
solid: true,
outline: true,
mini: true,
},
},
}),
],
}
```
### 6. 工具函数
#### 6.1 类名合并工具
```typescript
// mini/src/utils/cn.ts
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from '@weapp-tailwindcss/merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
#### 6.2 小程序专用类名处理
```typescript
// 小程序环境下的类名合并
import { twMerge } from '@weapp-tailwindcss/merge'
// 标准用法(自动处理小程序转义)
const classes = twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hovercbg-dark-red p-3 bg-_hB91C1C_'
// 手动指定版本(如果需要)
import { twMerge as twMergeV4 } from '@weapp-tailwindcss/merge/v4'
import { twMerge as twMergeV3 } from '@weapp-tailwindcss/merge/v3'
// 使用cva进行组件变体管理
import { cva } from 'class-variance-authority'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium',
{
variants: {
variant: {
default: 'bg-blue-500 text-white hover:bg-blue-600',
destructive: 'bg-red-500 text-white hover:bg-red-600',
},
size: {
sm: 'h-8 px-3 text-xs',
lg: 'h-12 px-6 text-base',
},
},
}
)
```
### 7. 最佳实践
#### 7.1 状态管理
```typescript
// 使用React Hook进行状态管理
const [loading, setLoading] = useState(false)
const [data, setData] = useState([])
// 加载状态显示
{loading ? (
) : (
{data.map(item => )}
)}
```
#### 7.2 错误处理
```typescript
// 错误状态展示
加载失败,请稍后重试
```
### 8. 性能优化
#### 8.1 样式优化
- 使用Tailwind的JIT模式,只生成用到的类名
- 避免内联样式,全部使用类名
- 合理使用`@apply`提取重复样式
#### 8.2 图标优化
- 使用CSS图标而非图片图标
- 图标按需加载,不使用的图标不会被打包
- 合理使用图标大小,避免过大图标
### 9. 调试工具
#### 9.1 开发调试
```typescript
// 添加调试样式类
调试内容
// 使用Tailwind的调试工具
// 在开发环境中添加
//
```
### 10. tailwind-merge使用规范
#### 10.1 基本用法
```typescript
// 单类名合并
const result = twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hovercbg-dark-red p-3 bg-_hB91C1C_'
// 处理冲突类名
twMerge('px-4', 'px-2') // → 'px-2'
twMerge('text-red-500', 'text-blue-500') // → 'text-blue-500'
```
#### 10.2 条件类名处理
```typescript
// 使用cn工具函数处理条件类名
import { cn } from '@/utils/cn'
const Button = ({ variant, size, disabled, className }) => {
return (
)
}
```
#### 10.3 小程序特殊处理
```typescript
// 跨端使用
import { create } from '@weapp-tailwindcss/merge'
const { twMerge } = create({
// 在当前环境为小程序时启用转义
disableEscape: true
})
// 版本选择
import { twMerge as twMergeV4 } from '@weapp-tailwindcss/merge/v4' // Tailwind v4
import { twMerge as twMergeV3 } from '@weapp-tailwindcss/merge/v3' // Tailwind v3
```
## 注意事项
1. **兼容性**:确保所有类名在小程序环境中有效
2. **性能**:避免过度嵌套和复杂选择器
3. **可维护性**:保持组件结构清晰,样式统一
4. **可读性**:合理使用空格和换行,提高代码可读性
5. **tailwind-merge**:始终使用twMerge或cn工具函数处理动态类名,避免类名冲突
6. **版本兼容**:根据Tailwind CSS版本选择正确的tailwind-merge版本