ui-guidelines
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUI Guidelines for Application
应用UI指南
Overview
概述
This skill provides comprehensive UI/UX guidelines for building components in a React/Next.js application using Ant Design, shadcn/ui, and consistent design tokens. It ensures all new components match the existing design system with proper colors, spacing, typography, and interaction patterns.
本技能提供了使用Ant Design、shadcn/ui和统一设计令牌在React/Next.js应用中构建组件的综合UI/UX指南。它确保所有新组件都能匹配现有设计系统,具备合适的颜色、间距、排版和交互模式。
When to Use This Skill
何时使用本技能
Trigger this skill when:
- Creating UI components: forms, tables, modals, cards, lists
- Adding new features that require UI elements
- Building data visualizations or dashboards
- Implementing loading states or animations
- Styling components to match the design system
- User asks to build/create/add any visual component
在以下场景触发本技能:
- 创建UI组件:表单、表格、模态框、卡片、列表
- 添加需要UI元素的新功能
- 构建数据可视化或仪表板
- 实现加载状态或动画
- 设置组件样式以匹配设计系统
- 用户要求构建/创建/添加任何可视化组件
Quick Start
快速开始
Step 1: Identify Component Type
步骤1:确定组件类型
Determine what you're building:
- Drawer/Side Panel → Read (Drawer Patterns section) [MANDATORY PATTERN]
references/component-patterns.md - Data Table → Read (Tables section)
references/codebase-patterns.md - Form/Modal → Read (Modal Patterns section)
references/codebase-patterns.md - Card/Grid → Read (Card Patterns section)
references/codebase-patterns.md - Need colors/spacing → Read
references/design-tokens.md - Need animations/loading → Read
references/animations.md
明确你要构建的组件类型:
- 抽屉/侧边面板 → 阅读(抽屉模式章节)[强制遵循模式]
references/component-patterns.md - 数据表格 → 阅读(表格章节)
references/codebase-patterns.md - 表单/模态框 → 阅读(模态框模式章节)
references/codebase-patterns.md - 卡片/网格 → 阅读(卡片模式章节)
references/codebase-patterns.md - 需要颜色/间距规范 → 阅读
references/design-tokens.md - 需要动画/加载效果 → 阅读
references/animations.md
Step 2: Follow the Component Checklist
步骤2:遵循组件检查清单
Every component must:
- Use Ant Design components as the base
- Apply consistent spacing (8px, 12px, 16px, 24px)
- Use theme tokens (,
token.colorText)token.colorBgContainer - Include proper TypeScript types
- Handle loading states (Skeleton, Spin, or loading prop)
- Show feedback with /
message.success()message.error() - Support responsive design
- Include proper error handling
每个组件必须满足以下要求:
- 以Ant Design组件为基础
- 应用统一间距(8px、12px、16px、24px)
- 使用主题令牌(、
token.colorText)token.colorBgContainer - 包含合适的TypeScript类型
- 处理加载状态(Skeleton、Spin或loading属性)
- 通过/
message.success()展示反馈message.error() - 支持响应式设计
- 包含完善的错误处理
Step 3: Apply Core Design Tokens
步骤3:应用核心设计令牌
Colors:
- Brand Orange: (primary brand color)
#F79402 - Product Owner: (purple)
#7C4DFF - Tech Owner: (green)
#52c41a - Error/Overdue: (red)
#ff4d4f - Always use for dynamic colors
theme.useToken()
Spacing:
- Small gap:
8px - Medium gap:
12px - Standard padding:
16px - Section margin:
24px
Typography:
- Table cells:
fontSize: 12 - Secondary text:
fontSize: '11px' - Strong text:
<Text strong> - Secondary:
<Text type="secondary">
颜色规范:
- 品牌橙色:(主品牌色)
#F79402 - 产品负责人:(紫色)
#7C4DFF - 技术负责人:(绿色)
#52c41a - 错误/逾期:(红色)
#ff4d4f - 始终使用获取动态颜色
theme.useToken()
间距规范:
- 小间距:
8px - 中等间距:
12px - 标准内边距:
16px - 区块外边距:
24px
排版规范:
- 表格单元格:
fontSize: 12 - 次要文本:
fontSize: '11px' - 加粗文本:
<Text strong> - 次要样式:
<Text type="secondary">
Core Patterns
核心模式
Pattern 1: Data Tables
模式1:数据表格
All data tables should follow this structure:
tsx
import { Table, Input, Select, ConfigProvider, theme } from "antd";
import { SearchOutlined } from "@ant-design/icons";
export default function DataTable() {
const { token } = theme.useToken();
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
{/* Filters row */}
<div style={{ marginBottom: 16, display: "flex", gap: "8px" }}>
<Input placeholder="Search..." prefix={<SearchOutlined />} style={{ flex: 1 }} allowClear />
<Select style={{ flex: 1 }} placeholder="Filter" allowClear />
</div>
{/* Table with custom theme */}
<ConfigProvider theme={{
components: { Table: { headerBg: token.colorBgContainer, fontSize: 12 } }
}}>
<Table
dataSource={data}
loading={isLoading}
rowKey="id"
size="small"
pagination={false}
scroll={{ y: 'calc(100vh - 220px)', x: 'max-content' }}
/>
</ConfigProvider>
</div>
);
}Key details:
- Use for table theme customization
ConfigProvider - Set for compact display
fontSize: 12 - Use for proper scrolling
scroll={{ y: 'calc(100vh - 220px)' }} - Always include
rowKey="id" - Set for compact tables
size="small"
所有数据表格应遵循以下结构:
tsx
import { Table, Input, Select, ConfigProvider, theme } from "antd";
import { SearchOutlined } from "@ant-design/icons";
export default function DataTable() {
const { token } = theme.useToken();
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
{/* Filters row */}
<div style={{ marginBottom: 16, display: "flex", gap: "8px" }}>
<Input placeholder="Search..." prefix={<SearchOutlined />} style={{ flex: 1 }} allowClear />
<Select style={{ flex: 1 }} placeholder="Filter" allowClear />
</div>
{/* Table with custom theme */}
<ConfigProvider theme={{
components: { Table: { headerBg: token.colorBgContainer, fontSize: 12 } }
}}>
<Table
dataSource={data}
loading={isLoading}
rowKey="id"
size="small"
pagination={false}
scroll={{ y: 'calc(100vh - 220px)', x: 'max-content' }}
/>
</ConfigProvider>
</div>
);
}关键细节:
- 使用自定义表格主题
ConfigProvider - 设置以实现紧凑显示
fontSize: 12 - 使用确保正确滚动
scroll={{ y: 'calc(100vh - 220px)' }} - 始终包含
rowKey="id" - 设置以创建紧凑表格
size="small"
Pattern 2: Forms in Modals
模式2:模态框中的表单
Standard form modal pattern:
tsx
import { Modal, Form, Input, Button, message } from "antd";
export default function AddModal({ isOpen, onClose, onSuccess }) {
const [form] = Form.useForm();
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async () => {
try {
const values = await form.validateFields();
setIsSubmitting(true);
await api.post('/endpoint', values);
message.success("Created successfully");
form.resetFields();
onSuccess();
onClose();
} catch (error) {
message.error(error.response?.data?.error || "Failed to create");
} finally {
setIsSubmitting(false);
}
};
return (
<Modal title="Add Item" open={isOpen} onCancel={onClose} footer={null} maskClosable={true}>
<Form form={form} layout="vertical" onFinish={handleSubmit}>
<Form.Item name="name" label="Name" rules={[{ required: true, message: "Please enter name" }]}>
<Input placeholder="Enter name" />
</Form.Item>
<Form.Item style={{ marginBottom: 0, marginTop: 16, textAlign: "right" }}>
<Button onClick={onClose} style={{ marginRight: 8 }}>Cancel</Button>
<Button htmlType="submit" loading={isSubmitting}>Create</Button>
</Form.Item>
</Form>
</Modal>
);
}Key details:
- Use for labels above inputs
layout="vertical" - Include validation rules with clear messages
- Reset form on success:
form.resetFields() - Show feedback: /
message.success()message.error() - Set for better UX
maskClosable={true}
标准表单模态框模式:
tsx
import { Modal, Form, Input, Button, message } from "antd";
export default function AddModal({ isOpen, onClose, onSuccess }) {
const [form] = Form.useForm();
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async () => {
try {
const values = await form.validateFields();
setIsSubmitting(true);
await api.post('/endpoint', values);
message.success("Created successfully");
form.resetFields();
onSuccess();
onClose();
} catch (error) {
message.error(error.response?.data?.error || "Failed to create");
} finally {
setIsSubmitting(false);
}
};
return (
<Modal title="Add Item" open={isOpen} onCancel={onClose} footer={null} maskClosable={true}>
<Form form={form} layout="vertical" onFinish={handleSubmit}>
<Form.Item name="name" label="Name" rules={[{ required: true, message: "Please enter name" }]}>
<Input placeholder="Enter name" />
</Form.Item>
<Form.Item style={{ marginBottom: 0, marginTop: 16, textAlign: "right" }}>
<Button onClick={onClose} style={{ marginRight: 8 }}>Cancel</Button>
<Button htmlType="submit" loading={isSubmitting}>Create</Button>
</Form.Item>
</Form>
</Modal>
);
}关键细节:
- 使用实现标签在输入框上方的布局
layout="vertical" - 包含带有清晰提示的验证规则
- 成功后重置表单:
form.resetFields() - 展示反馈:/
message.success()message.error() - 设置以提升用户体验
maskClosable={true}
Pattern 3: Selectable Card Grids
模式3:可选择的卡片网格
Horizontal scrolling cards with selection:
tsx
import { theme, Typography, Avatar } from "antd";
const { Text } = Typography;
const { token } = theme.useToken();
<div style={{
display: "flex",
gap: "12px",
overflowX: "auto",
paddingBottom: "4px"
}}>
{items.map((item) => {
const isSelected = selectedId === item.id;
return (
<div
key={item.id}
onClick={() => setSelectedId(isSelected ? null : item.id)}
style={{
flex: 1,
minWidth: '200px',
maxWidth: '280px',
padding: '12px',
cursor: 'pointer',
borderRadius: '8px',
border: isSelected ? '1px solid #F79400' : `1px solid ${token.colorBorder}`,
backgroundColor: isSelected ? token.colorFillSecondary : token.colorBgContainer,
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.04)',
}}
>
<Text strong style={{ fontSize: '14px' }}>{item.name}</Text>
{/* Additional content */}
</div>
);
})}
</div>Key details:
- Selected state: border with brand primary color
- Subtle shadow:
0 1px 2px rgba(0, 0, 0, 0.04) - Border radius:
8px - Use for unselected state
token.colorBorder
支持横向滚动的可选择卡片:
tsx
import { theme, Typography, Avatar } from "antd";
const { Text } = Typography;
const { token } = theme.useToken();
<div style={{
display: "flex",
gap: "12px",
overflowX: "auto",
paddingBottom: "4px"
}}>
{items.map((item) => {
const isSelected = selectedId === item.id;
return (
<div
key={item.id}
onClick={() => setSelectedId(isSelected ? null : item.id)}
style={{
flex: 1,
minWidth: '200px',
maxWidth: '280px',
padding: '12px',
cursor: 'pointer',
borderRadius: '8px',
border: isSelected ? '1px solid #F79400' : `1px solid ${token.colorBorder}`,
backgroundColor: isSelected ? token.colorFillSecondary : token.colorBgContainer,
boxShadow: '0 1px 2px rgba(0, 0, 0, 0.04)',
}}
>
<Text strong style={{ fontSize: '14px' }}>{item.name}</Text>
{/* Additional content */}
</div>
);
})}
</div>关键细节:
- 选中状态:使用品牌主色作为边框
- 轻微阴影:
0 1px 2px rgba(0, 0, 0, 0.04) - 圆角:
8px - 未选中状态使用
token.colorBorder
Pattern 4: Loading States
模式4:加载状态
Always show loading feedback:
tsx
// Table loading
<Table loading={isLoading} dataSource={data} />
// Card loading skeleton
{data === undefined ? (
<Card loading style={{ minWidth: '200px' }} />
) : (
<Card>{content}</Card>
)}
// Button loading
<Button htmlType="submit" loading={isSubmitting}>Submit</Button>
// Page content skeleton
<Skeleton active paragraph={{ rows: 4 }} />始终展示加载反馈:
tsx
// Table loading
<Table loading={isLoading} dataSource={data} />
// Card loading skeleton
{data === undefined ? (
<Card loading style={{ minWidth: '200px' }} />
) : (
<Card>{content}</Card>
)}
// Button loading
<Button htmlType="submit" loading={isSubmitting}>Submit</Button>
// Page content skeleton
<Skeleton active paragraph={{ rows: 4 }} />Pattern 5: Avatars with Fallbacks
模式5:带有回退的头像
tsx
{user.profilePic ? (
<Avatar size={24} src={getCachedAvatarUrl(user.profilePic)} />
) : (
<Avatar size={24} style={{ backgroundColor: getAvatarColor(user.name) }}>
{user.name.charAt(0).toUpperCase()}
</Avatar>
)}tsx
{user.profilePic ? (
<Avatar size={24} src={getCachedAvatarUrl(user.profilePic)} />
) : (
<Avatar size={24} style={{ backgroundColor: getAvatarColor(user.name) }}>
{user.name.charAt(0).toUpperCase()}
</Avatar>
)}Styling Approach
样式方法
Priority Order
优先级顺序
- Ant Design props first (type, size, danger, etc.)
- Theme tokens for colors ()
token.colorBgContainer - Inline styles for layout and spacing
- Tailwind rarely (only for utility classes)
- 优先使用Ant Design属性(type、size、danger等)
- 使用主题令牌设置颜色()
token.colorBgContainer - 内联样式用于布局和间距
- 尽量少用Tailwind(仅用于工具类)
DO's ✅
注意事项 ✅
- Use Ant Design components as base
- Use for colors
theme.useToken() - Apply consistent spacing (8px, 12px, 16px, 24px)
- Include loading states everywhere
- Show user feedback with messages
- Handle errors gracefully
- Use TypeScript types
- 以Ant Design组件为基础
- 使用获取颜色
theme.useToken() - 应用统一间距(8px、12px、16px、24px)
- 所有地方都包含加载状态
- 通过消息提示向用户展示反馈
- 优雅处理错误
- 使用TypeScript类型
DON'Ts ❌
禁止事项 ❌
- Don't use CSS-in-JS libraries
- Don't create custom CSS files
- Don't hardcode colors (use tokens)
- Don't skip error handling
- Don't ignore responsive design
- Don't use excessive shadows
- 不要使用CSS-in-JS库
- 不要创建自定义CSS文件
- 不要硬编码颜色(使用令牌)
- 不要跳过错误处理
- 不要忽略响应式设计
- 不要使用过多阴影
Common Recipes
常用示例
Status Tag
状态标签
tsx
<Tag color={status.color || "#d9d9d9"} style={{ borderRadius: "8px", fontSize: 12 }}>
{status.name || "Not Set"}
</Tag>tsx
<Tag color={status.color || "#d9d9d9"} style={{ borderRadius: "8px", fontSize: 12 }}>
{status.name || "Not Set"}
</Tag>Clickable Text
可点击文本
tsx
<Text strong style={{ cursor: 'pointer', fontSize: 12 }} onClick={() => router.push(`/path/${id}`)}>
{title}
</Text>tsx
<Text strong style={{ cursor: 'pointer', fontSize: 12 }} onClick={() => router.push(`/path/${id}`)}>
{title}
</Text>Overdue Indicator
逾期指示器
tsx
{isOverdue && (
<Tooltip title={`Overdue since ${date}`}>
<div style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#ff4d4f' }} />
</Tooltip>
)}tsx
{isOverdue && (
<Tooltip title={`Overdue since ${date}`}>
<div style={{ width: '6px', height: '6px', borderRadius: '50%', backgroundColor: '#ff4d4f' }} />
</Tooltip>
)}Select with Item Counts
包含项目数量的选择器
tsx
<Select>
{items.map(item => (
<Option key={item.id} value={item.id}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>{item.name}</span>
<Text type="secondary" style={{ fontSize: '11px' }}>{item.count} items</Text>
</div>
</Option>
))}
</Select>tsx
<Select>
{items.map(item => (
<Option key={item.id} value={item.id}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>{item.name}</span>
<Text type="secondary" style={{ fontSize: '11px' }}>{item.count} items</Text>
</div>
</Option>
))}
</Select>Reference Files
参考文件
Read these files for detailed information:
- design-tokens.md - Colors, spacing, typography system
- codebase-patterns.md - Real patterns from existing code
- component-patterns.md - Ant Design component standards
- styling-layout.md - Layout patterns and responsive design
- animations.md - Loading indicators and transitions
阅读以下文件获取详细信息:
- design-tokens.md - 颜色、间距、排版系统
- codebase-patterns.md - 现有代码中的实际模式
- component-patterns.md - Ant Design组件标准
- styling-layout.md - 布局模式和响应式设计
- animations.md - 加载指示器和过渡效果
Decision Tree
决策树
Building something new?
- Is it a table? → Read Tables section
codebase-patterns.md - Is it a form? → Read Modal Patterns section
codebase-patterns.md - Is it a card grid? → Read Card Patterns section
codebase-patterns.md - Need specific colors? → Read
design-tokens.md - Need loading animation? → Read
animations.md
For ANY component:
- Use TypeScript
- Handle loading states
- Show error messages
- Use theme tokens
- Test responsiveness
要构建新组件?
- 是表格吗? → 阅读的表格章节
codebase-patterns.md - 是表单吗? → 阅读的模态框模式章节
codebase-patterns.md - 是卡片网格吗? → 阅读的卡片模式章节
codebase-patterns.md - 需要特定颜色? → 阅读
design-tokens.md - 需要加载动画? → 阅读
animations.md
对于任何组件:
- 使用TypeScript
- 处理加载状态
- 展示错误消息
- 使用主题令牌
- 测试响应式效果
Typography Scale
排版层级
tsx
// Strong text (table headers, card titles)
<Text strong style={{ fontSize: '12px' }}>Title</Text>
// Regular text (table cells, body)
<Text style={{ fontSize: '12px' }}>Content</Text>
// Secondary text (subtitles, metadata)
<Text type="secondary" style={{ fontSize: '11px' }}>Metadata</Text>
// Tertiary text (additional info)
<Text style={{ fontSize: '11px', color: token.colorTextTertiary }}>Info</Text>tsx
// 加粗文本(表格标题、卡片标题)
<Text strong style={{ fontSize: '12px' }}>Title</Text>
// 常规文本(表格单元格、正文)
<Text style={{ fontSize: '12px' }}>Content</Text>
// 次要文本(副标题、元数据)
<Text type="secondary" style={{ fontSize: '11px' }}>Metadata</Text>
// 三级文本(附加信息)
<Text style={{ fontSize: '11px', color: token.colorTextTertiary }}>Info</Text>Page Layout
页面布局
Standard full-height page layout:
tsx
export default function Page() {
return (
<div style={{
height: "100%",
display: "flex",
flexDirection: "column",
overflow: "hidden",
padding: "24px 40px 24px 24px"
}}>
{/* Page content with proper scrolling */}
</div>
);
}标准全屏页面布局:
tsx
export default function Page() {
return (
<div style={{
height: "100%",
display: "flex",
flexDirection: "column",
overflow: "hidden",
padding: "24px 40px 24px 24px"
}}>
{/* Page content with proper scrolling */}
</div>
);
}Data Fetching
数据获取
Use SWR for data fetching:
tsx
import useSWR from "swr";
import { fetcher } from "@/lib/axios";
const { data, error, isLoading, mutate } = useSWR(
'/api/endpoint',
fetcher,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);使用SWR进行数据获取:
tsx
import useSWR from "swr";
import { fetcher } from "@/lib/axios";
const { data, error, isLoading, mutate } = useSWR(
'/api/endpoint',
fetcher,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);Final Checklist
最终检查清单
Before completing any component:
- Uses Ant Design as base
- Applies theme tokens for colors
- Has consistent spacing
- Includes loading states
- Shows error feedback
- Has TypeScript types
- Works responsively
- Matches existing patterns
- Uses for tables
fontSize: 12 - Includes proper validation
完成任何组件前,请检查:
- 以Ant Design为基础
- 使用主题令牌设置颜色
- 具备统一间距
- 包含加载状态
- 展示错误反馈
- 具备TypeScript类型
- 支持响应式
- 匹配现有模式
- 表格使用
fontSize: 12 - 包含合适的验证