@famgia/omnify-ai-guides 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/chunk-RCTEXK7C.js +549 -0
- package/dist/chunk-RCTEXK7C.js.map +1 -0
- package/dist/config/rules.yaml +524 -0
- package/dist/index.cjs +587 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/agents/architect.md.stub +150 -0
- package/dist/knowledge/agents/developer.md.stub +190 -0
- package/dist/knowledge/agents/reviewer.md.stub +134 -0
- package/dist/knowledge/agents/tester.md.stub +196 -0
- package/dist/knowledge/checklists/backend.md.stub +112 -0
- package/dist/knowledge/checklists/react.md.stub +108 -0
- package/dist/knowledge/claude-rules/laravel-controllers.md.stub +57 -0
- package/dist/knowledge/claude-rules/laravel-migrations.md.stub +47 -0
- package/dist/knowledge/claude-rules/laravel-tests.md.stub +52 -0
- package/dist/knowledge/claude-rules/naming.md.stub +369 -0
- package/dist/knowledge/claude-rules/performance.md.stub +256 -0
- package/dist/knowledge/claude-rules/php-standards.md.stub +305 -0
- package/dist/knowledge/claude-rules/react-components.md.stub +67 -0
- package/dist/knowledge/claude-rules/schema-yaml.md.stub +83 -0
- package/dist/knowledge/claude-rules/security.md.stub +164 -0
- package/dist/knowledge/cursor-rules/antd-deprecations.mdc.stub +62 -0
- package/dist/knowledge/cursor-rules/basemodel-readonly.mdc.stub +66 -0
- package/dist/knowledge/cursor-rules/baserequest-readonly.mdc.stub +74 -0
- package/dist/knowledge/cursor-rules/baseresource-readonly.mdc.stub +78 -0
- package/dist/knowledge/cursor-rules/laravel-controller.mdc.stub +421 -0
- package/dist/knowledge/cursor-rules/laravel-request.mdc.stub +112 -0
- package/dist/knowledge/cursor-rules/laravel-resource.mdc.stub +73 -0
- package/dist/knowledge/cursor-rules/laravel-review.mdc.stub +69 -0
- package/dist/knowledge/cursor-rules/laravel-testing.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/laravel.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/migrations-workflow.mdc.stub +224 -0
- package/dist/knowledge/cursor-rules/model-editable.mdc.stub +120 -0
- package/dist/knowledge/cursor-rules/omnify-migrations.mdc.stub +109 -0
- package/dist/knowledge/cursor-rules/omnify-schema.mdc.stub +358 -0
- package/dist/knowledge/cursor-rules/omnify.mdc.stub +58 -0
- package/dist/knowledge/cursor-rules/react-design.mdc.stub +693 -0
- package/dist/knowledge/cursor-rules/react-form.mdc.stub +292 -0
- package/dist/knowledge/cursor-rules/react-services.mdc.stub +304 -0
- package/dist/knowledge/cursor-rules/react.mdc.stub +336 -0
- package/dist/knowledge/cursor-rules/request-editable.mdc.stub +111 -0
- package/dist/knowledge/cursor-rules/resource-editable.mdc.stub +125 -0
- package/dist/knowledge/cursor-rules/schema-create.mdc.stub +440 -0
- package/dist/knowledge/cursor-rules/validation-rules.mdc.stub +181 -0
- package/dist/knowledge/laravel/README.md.stub +59 -0
- package/dist/knowledge/laravel/architecture.md.stub +424 -0
- package/dist/knowledge/laravel/authentication.md.stub +588 -0
- package/dist/knowledge/laravel/controller.md.stub +484 -0
- package/dist/knowledge/laravel/datetime.md.stub +334 -0
- package/dist/knowledge/laravel/migrations-team.md.stub +376 -0
- package/dist/knowledge/laravel/openapi.md.stub +449 -0
- package/dist/knowledge/laravel/request.md.stub +450 -0
- package/dist/knowledge/laravel/resource.md.stub +516 -0
- package/dist/knowledge/laravel/service.md.stub +503 -0
- package/dist/knowledge/laravel/testing.md.stub +1504 -0
- package/dist/knowledge/omnify/antdesign-guide.md.stub +401 -0
- package/dist/knowledge/omnify/config-guide.md.stub +405 -0
- package/dist/knowledge/omnify/japan-guide.md.stub +186 -0
- package/dist/knowledge/omnify/laravel-guide.md.stub +61 -0
- package/dist/knowledge/omnify/partial-schema-guide.md.stub +353 -0
- package/dist/knowledge/omnify/react-form-guide.md.stub +225 -0
- package/dist/knowledge/omnify/schema-guide.md.stub +144 -0
- package/dist/knowledge/omnify/typescript-guide.md.stub +337 -0
- package/dist/knowledge/react/README.md.stub +221 -0
- package/dist/knowledge/react/antd-guide.md +528 -0
- package/dist/knowledge/react/antd-guide.md.stub +528 -0
- package/dist/knowledge/react/checklist.md.stub +108 -0
- package/dist/knowledge/react/datetime-guide.md.stub +137 -0
- package/dist/knowledge/react/design-philosophy.md.stub +363 -0
- package/dist/knowledge/react/i18n-guide.md.stub +211 -0
- package/dist/knowledge/react/laravel-integration.md.stub +181 -0
- package/dist/knowledge/react/service-pattern.md.stub +180 -0
- package/dist/knowledge/react/tanstack-query.md.stub +339 -0
- package/dist/knowledge/react/types-guide.md +669 -0
- package/dist/knowledge/react/types-guide.md.stub +669 -0
- package/dist/knowledge/workflows/bug-fix.md.stub +201 -0
- package/dist/knowledge/workflows/code-review.md.stub +164 -0
- package/dist/knowledge/workflows/new-feature.md.stub +327 -0
- package/dist/plugin-M95GyBll.d.cts +191 -0
- package/dist/plugin-M95GyBll.d.ts +191 -0
- package/dist/plugin.cjs +573 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +2 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.js +15 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
# Ant Design Guide
|
|
2
|
+
|
|
3
|
+
> **Related:** [README](./README.md) | [i18n](./i18n-guide.md)
|
|
4
|
+
|
|
5
|
+
## ⚠️ IMPORTANT: Use Ant Design First
|
|
6
|
+
|
|
7
|
+
**ALWAYS check if Ant Design has a component before creating your own.**
|
|
8
|
+
|
|
9
|
+
Ant Design provides 60+ components: https://ant.design/components/overview
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// ✅ DO: Use Ant Design components
|
|
13
|
+
import { Table, Form, Input, Button, Modal, Card, Descriptions } from "antd";
|
|
14
|
+
|
|
15
|
+
// ❌ DON'T: Create custom components that Ant Design already has
|
|
16
|
+
// DON'T create: CustomTable, CustomModal, CustomForm, CustomButton
|
|
17
|
+
// DON'T create: DataGrid, Popup, FormInput
|
|
18
|
+
|
|
19
|
+
// ✅ DO: Extend Ant Design if needed
|
|
20
|
+
function UserTable(props: { users: User[] }) {
|
|
21
|
+
return <Table dataSource={props.users} columns={...} />; // Wraps AntD Table
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ❌ DON'T: Build from scratch
|
|
25
|
+
function UserTable(props: { users: User[] }) {
|
|
26
|
+
return <table><tbody>{users.map(...)}</tbody></table>; // WRONG!
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## ⚠️ No New Libraries Without Permission
|
|
33
|
+
|
|
34
|
+
**DO NOT install new npm packages without explicit user approval.**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# ❌ DON'T: Install without asking
|
|
38
|
+
npm install lodash
|
|
39
|
+
npm install moment
|
|
40
|
+
npm install react-table
|
|
41
|
+
|
|
42
|
+
# ✅ DO: Ask first
|
|
43
|
+
"Do you want to install library X for Y?"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Already installed libraries (use these):**
|
|
47
|
+
- UI: `antd`, `@ant-design/icons`
|
|
48
|
+
- HTTP: `axios`
|
|
49
|
+
- State: `@tanstack/react-query`
|
|
50
|
+
- Styling: `tailwindcss`
|
|
51
|
+
- i18n: `next-intl`
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## When to Create a Component
|
|
56
|
+
|
|
57
|
+
| Create Component | Don't Create |
|
|
58
|
+
| ------------------------------- | ----------------------------- |
|
|
59
|
+
| Used in 2+ places | Used only once |
|
|
60
|
+
| Has own state/logic (>50 lines) | Simple markup (<30 lines) |
|
|
61
|
+
| Needs unit testing | Trivial display |
|
|
62
|
+
| Complex props interface | Few inline props |
|
|
63
|
+
| **Ant Design doesn't have it** | **Ant Design already has it** |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Container vs Presentational
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// CONTAINER COMPONENT (Smart) - pages or complex components
|
|
72
|
+
// - Fetches data
|
|
73
|
+
// - Handles mutations
|
|
74
|
+
// - Contains business logic
|
|
75
|
+
// ============================================================================
|
|
76
|
+
|
|
77
|
+
// app/(dashboard)/users/page.tsx
|
|
78
|
+
"use client";
|
|
79
|
+
|
|
80
|
+
import { useState } from "react";
|
|
81
|
+
import { useQuery } from "@tanstack/react-query";
|
|
82
|
+
import { userService, UserListParams } from "@/services/users";
|
|
83
|
+
import { queryKeys } from "@/lib/queryKeys";
|
|
84
|
+
import { UserTable } from "@/components/tables/UserTable";
|
|
85
|
+
|
|
86
|
+
export default function UsersPage() {
|
|
87
|
+
const [filters, setFilters] = useState<UserListParams>({ page: 1 });
|
|
88
|
+
|
|
89
|
+
const { data, isLoading } = useQuery({
|
|
90
|
+
queryKey: queryKeys.users.list(filters),
|
|
91
|
+
queryFn: () => userService.list(filters),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<UserTable
|
|
96
|
+
users={data?.data ?? []}
|
|
97
|
+
loading={isLoading}
|
|
98
|
+
pagination={data?.meta}
|
|
99
|
+
onPageChange={(page) => setFilters({ ...filters, page })}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// PRESENTATIONAL COMPONENT (Dumb) - reusable UI
|
|
106
|
+
// - Receives data via props
|
|
107
|
+
// - No data fetching
|
|
108
|
+
// - No business logic
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
// components/tables/UserTable.tsx
|
|
112
|
+
import { Table } from "antd";
|
|
113
|
+
import type { User } from "@omnify/schemas";
|
|
114
|
+
import type { PaginatedResponse } from "@/lib/api";
|
|
115
|
+
|
|
116
|
+
interface UserTableProps {
|
|
117
|
+
users: User[];
|
|
118
|
+
loading: boolean;
|
|
119
|
+
pagination?: PaginatedResponse<User>["meta"];
|
|
120
|
+
onPageChange: (page: number) => void;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function UserTable({ users, loading, pagination, onPageChange }: UserTableProps) {
|
|
124
|
+
return (
|
|
125
|
+
<Table
|
|
126
|
+
dataSource={users}
|
|
127
|
+
loading={loading}
|
|
128
|
+
rowKey="id"
|
|
129
|
+
pagination={{
|
|
130
|
+
current: pagination?.current_page,
|
|
131
|
+
total: pagination?.total,
|
|
132
|
+
onChange: onPageChange,
|
|
133
|
+
}}
|
|
134
|
+
columns={[
|
|
135
|
+
{ title: "ID", dataIndex: "id" },
|
|
136
|
+
{ title: "Name", dataIndex: "name" },
|
|
137
|
+
{ title: "Email", dataIndex: "email" },
|
|
138
|
+
]}
|
|
139
|
+
/>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Form Pattern with Laravel Validation
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
"use client";
|
|
150
|
+
|
|
151
|
+
import { Form, Input, Button, message } from "antd";
|
|
152
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
153
|
+
import { useTranslations } from "next-intl";
|
|
154
|
+
import { getFormErrors } from "@/lib/api";
|
|
155
|
+
import { queryKeys } from "@/lib/queryKeys";
|
|
156
|
+
import { userService } from "@/services/users";
|
|
157
|
+
|
|
158
|
+
export default function UserForm() {
|
|
159
|
+
const t = useTranslations();
|
|
160
|
+
const [form] = Form.useForm();
|
|
161
|
+
const queryClient = useQueryClient();
|
|
162
|
+
|
|
163
|
+
const mutation = useMutation({
|
|
164
|
+
mutationFn: userService.create,
|
|
165
|
+
onSuccess: () => {
|
|
166
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.users.all });
|
|
167
|
+
message.success(t("messages.created"));
|
|
168
|
+
form.resetFields();
|
|
169
|
+
},
|
|
170
|
+
onError: (error) => {
|
|
171
|
+
// This maps Laravel's 422 { errors: { email: ["Already exists"] } }
|
|
172
|
+
// to Ant Design's form.setFields format
|
|
173
|
+
form.setFields(getFormErrors(error));
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<Form
|
|
179
|
+
form={form}
|
|
180
|
+
layout="vertical"
|
|
181
|
+
onFinish={(values) => mutation.mutate(values)}
|
|
182
|
+
>
|
|
183
|
+
<Form.Item
|
|
184
|
+
name="name"
|
|
185
|
+
label={t("common.name")}
|
|
186
|
+
rules={[{ required: true }]}
|
|
187
|
+
>
|
|
188
|
+
<Input />
|
|
189
|
+
</Form.Item>
|
|
190
|
+
|
|
191
|
+
<Form.Item
|
|
192
|
+
name="email"
|
|
193
|
+
label={t("auth.email")}
|
|
194
|
+
rules={[{ required: true }, { type: "email" }]}
|
|
195
|
+
>
|
|
196
|
+
<Input />
|
|
197
|
+
</Form.Item>
|
|
198
|
+
|
|
199
|
+
<Form.Item>
|
|
200
|
+
<Button
|
|
201
|
+
type="primary"
|
|
202
|
+
htmlType="submit"
|
|
203
|
+
loading={mutation.isPending}
|
|
204
|
+
>
|
|
205
|
+
{t("common.save")}
|
|
206
|
+
</Button>
|
|
207
|
+
</Form.Item>
|
|
208
|
+
</Form>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## ⚠️ Ant Design Breaking Changes & Deprecated Props
|
|
216
|
+
|
|
217
|
+
> **IMPORTANT**: Check your `package.json` to determine which Ant Design version you're using:
|
|
218
|
+
> - **Ant Design 5.x**: Use `visible`, `valueStyle`, `bodyStyle`, `headStyle` (deprecated but still work)
|
|
219
|
+
> - **Ant Design 6.x**: Use `open`, `styles={{ ... }}` (semantic DOM API)
|
|
220
|
+
|
|
221
|
+
### Deprecated Props Reference Table
|
|
222
|
+
|
|
223
|
+
| Component | ❌ Deprecated (v6+) | ✅ Use Instead (v6+) | Notes |
|
|
224
|
+
| ----------------------- | -------------------------- | -------------------------- | -------------------------------------- |
|
|
225
|
+
| **Statistic** | `valueStyle` | `styles={{ content: {} }}` | ⚠️ v6.0.0+ only! Use `valueStyle` in v5 |
|
|
226
|
+
| **Card** | `bodyStyle` | `styles={{ body: {} }}` | ⚠️ v6.0.0+ only! Use `bodyStyle` in v5 |
|
|
227
|
+
| **Card** | `headStyle` | `styles={{ header: {} }}` | ⚠️ v6.0.0+ only! Use `headStyle` in v5 |
|
|
228
|
+
| **Divider** | `orientation` | `titlePlacement` | `orientation` is for direction only |
|
|
229
|
+
| Modal | `visible` | `open` | v5.0.0+ |
|
|
230
|
+
| Drawer | `visible` | `open` | v5.0.0+ |
|
|
231
|
+
| Dropdown | `visible` | `open` | v5.0.0+ |
|
|
232
|
+
| Tooltip | `visible` | `open` | v5.0.0+ |
|
|
233
|
+
| Popover | `visible` | `open` | v5.0.0+ |
|
|
234
|
+
| Popconfirm | `visible` | `open` | v5.0.0+ |
|
|
235
|
+
| Select | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | v5.0.0+ |
|
|
236
|
+
| TreeSelect | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | v5.0.0+ |
|
|
237
|
+
| Cascader | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | v5.0.0+ |
|
|
238
|
+
| AutoComplete | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | v5.0.0+ |
|
|
239
|
+
| Table | `filterDropdownVisible` | `filterDropdownOpen` | v5.0.0+ |
|
|
240
|
+
| DatePicker | `dropdownClassName` | `popupClassName` | v5.0.0+ |
|
|
241
|
+
| TimePicker | `dropdownClassName` | `popupClassName` | v5.0.0+ |
|
|
242
|
+
| Mentions | `dropdownClassName` | `popupClassName` | v5.0.0+ |
|
|
243
|
+
| Tag | `closable` | `closeIcon={false}` | Use `closeIcon={false}` to hide |
|
|
244
|
+
| **List** | (component) | Use `Table` or custom | DEPRECATED in v6.0.0 |
|
|
245
|
+
| **Statistic.Countdown** | (component) | `Statistic.Timer` | Use `Statistic.Timer` (v5.25.0+) |
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// ❌ DON'T: Use deprecated props (causes console warnings)
|
|
249
|
+
<Statistic value={100} valueStyle={{ color: 'green' }} />
|
|
250
|
+
<Card bodyStyle={{ padding: 0 }} headStyle={{ background: '#f5f5f5' }}>
|
|
251
|
+
<Divider orientation="left">Title</Divider>
|
|
252
|
+
<Modal visible={isOpen}>
|
|
253
|
+
|
|
254
|
+
// ✅ DO: Use new props (Ant Design 6+)
|
|
255
|
+
<Statistic value={100} styles={{ content: { color: 'green' } }} />
|
|
256
|
+
<Card styles={{ body: { padding: 0 }, header: { background: '#f5f5f5' } }}>
|
|
257
|
+
<Divider titlePlacement="left">Title</Divider>
|
|
258
|
+
<Modal open={isOpen}>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 🎨 Ant Design 6.0 Semantic DOM API (NEW!)
|
|
264
|
+
|
|
265
|
+
**Version 6.0.0** introduced a new **Semantic DOM** pattern for styling. Instead of single style props, use `styles` and `classNames` objects:
|
|
266
|
+
|
|
267
|
+
### Statistic - Semantic Structure
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
// Semantic keys: root, header, title, prefix, content, suffix
|
|
271
|
+
|
|
272
|
+
// ❌ OLD (deprecated in v6)
|
|
273
|
+
<Statistic
|
|
274
|
+
value={112893}
|
|
275
|
+
valueStyle={{ color: token.colorSuccess }}
|
|
276
|
+
prefix={<ArrowUpOutlined />}
|
|
277
|
+
/>
|
|
278
|
+
|
|
279
|
+
// ✅ NEW (v6.0.0+)
|
|
280
|
+
<Statistic
|
|
281
|
+
value={112893}
|
|
282
|
+
styles={{
|
|
283
|
+
content: { color: token.colorSuccess },
|
|
284
|
+
prefix: { marginRight: 8 },
|
|
285
|
+
}}
|
|
286
|
+
classNames={{
|
|
287
|
+
root: 'my-statistic',
|
|
288
|
+
content: 'my-statistic-value',
|
|
289
|
+
}}
|
|
290
|
+
prefix={<ArrowUpOutlined />}
|
|
291
|
+
/>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Card - Semantic Structure
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// Semantic keys: root, header, title, extra, body, actions, cover
|
|
298
|
+
|
|
299
|
+
// ❌ OLD (deprecated)
|
|
300
|
+
<Card bodyStyle={{ padding: 0 }} headStyle={{ background: '#fafafa' }}>
|
|
301
|
+
|
|
302
|
+
// ✅ NEW (v6.0.0+)
|
|
303
|
+
<Card styles={{ body: { padding: 0 }, header: { background: '#fafafa' } }}>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Common Components with Semantic DOM (v6.0.0+)
|
|
307
|
+
|
|
308
|
+
| Component | Semantic Keys |
|
|
309
|
+
| ------------ | ------------------------------------------------------------- |
|
|
310
|
+
| Statistic | `root`, `header`, `title`, `prefix`, `content`, `suffix` |
|
|
311
|
+
| Card | `root`, `header`, `title`, `extra`, `body`, `actions` |
|
|
312
|
+
| Modal | `root`, `header`, `title`, `body`, `footer`, `mask` |
|
|
313
|
+
| Drawer | `root`, `header`, `title`, `body`, `footer`, `mask` |
|
|
314
|
+
| Table | `root`, `header`, `body`, `footer`, `cell` |
|
|
315
|
+
| Form | `root`, `item`, `label`, `input`, `feedback` |
|
|
316
|
+
| Descriptions | `root`, `header`, `title`, `body`, `item`, `label`, `content` |
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// General pattern for semantic styling
|
|
320
|
+
<Component
|
|
321
|
+
styles={{ [semanticKey]: { /* CSSProperties */ } }}
|
|
322
|
+
classNames={{ [semanticKey]: 'my-class' }}
|
|
323
|
+
/>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 🚨 Common Ant Design 6+ Mistakes
|
|
329
|
+
|
|
330
|
+
### 1. Divider - `orientation` vs `titlePlacement`
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// ❌ WRONG: This will show a deprecation warning!
|
|
334
|
+
<Divider orientation="left">Section Title</Divider>
|
|
335
|
+
// Warning: [antd: Divider] `orientation` is used for direction, please use `titlePlacement` replace this
|
|
336
|
+
|
|
337
|
+
// ✅ CORRECT: Use titlePlacement for title position
|
|
338
|
+
<Divider titlePlacement="left">Section Title</Divider>
|
|
339
|
+
<Divider titlePlacement="center">Section Title</Divider>
|
|
340
|
+
<Divider titlePlacement="right">Section Title</Divider>
|
|
341
|
+
|
|
342
|
+
// For horizontal/vertical dividers, use `type`:
|
|
343
|
+
<Divider type="horizontal" /> // default
|
|
344
|
+
<Divider type="vertical" />
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 2. Modal/Drawer - `visible` vs `open`
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
// ❌ WRONG
|
|
351
|
+
const [visible, setVisible] = useState(false);
|
|
352
|
+
<Modal visible={visible} onCancel={() => setVisible(false)}>
|
|
353
|
+
|
|
354
|
+
// ✅ CORRECT
|
|
355
|
+
const [open, setOpen] = useState(false);
|
|
356
|
+
<Modal open={open} onCancel={() => setOpen(false)}>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### 3. Form.Item - `dependencies` must be array
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// ❌ WRONG: dependencies as string
|
|
363
|
+
<Form.Item dependencies="password">
|
|
364
|
+
|
|
365
|
+
// ✅ CORRECT: dependencies as array
|
|
366
|
+
<Form.Item dependencies={['password']}>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### 4. Table - Column `render` function signature
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
// ❌ WRONG: Using wrong parameter order
|
|
373
|
+
columns={[{
|
|
374
|
+
render: (record, text) => <span>{text}</span> // WRONG ORDER!
|
|
375
|
+
}]}
|
|
376
|
+
|
|
377
|
+
// ✅ CORRECT: (text, record, index)
|
|
378
|
+
columns={[{
|
|
379
|
+
render: (text, record, index) => <span>{text}</span>
|
|
380
|
+
}]}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### 5. Select/TreeSelect - Option rendering
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
// ❌ WRONG: Using children in v6+
|
|
387
|
+
<Select>
|
|
388
|
+
<Select.Option value="1">Option 1</Select.Option>
|
|
389
|
+
</Select>
|
|
390
|
+
|
|
391
|
+
// ✅ PREFERRED: Use options prop (better performance)
|
|
392
|
+
<Select options={[
|
|
393
|
+
{ value: '1', label: 'Option 1' },
|
|
394
|
+
{ value: '2', label: 'Option 2' },
|
|
395
|
+
]} />
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 6. DatePicker - Dayjs instead of Moment
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// ❌ WRONG: Ant Design 6+ uses dayjs, not moment
|
|
402
|
+
import moment from 'moment';
|
|
403
|
+
<DatePicker value={moment(date)} />
|
|
404
|
+
|
|
405
|
+
// ✅ CORRECT: Use dayjs
|
|
406
|
+
import dayjs from 'dayjs';
|
|
407
|
+
<DatePicker value={dayjs(date)} />
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 7. ConfigProvider - Theme customization
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// ❌ WRONG: Old less variable approach
|
|
414
|
+
@primary-color: #1890ff;
|
|
415
|
+
|
|
416
|
+
// ✅ CORRECT: Use ConfigProvider theme token
|
|
417
|
+
<ConfigProvider
|
|
418
|
+
theme={{
|
|
419
|
+
token: {
|
|
420
|
+
colorPrimary: '#1890ff',
|
|
421
|
+
borderRadius: 6,
|
|
422
|
+
},
|
|
423
|
+
}}
|
|
424
|
+
>
|
|
425
|
+
<App />
|
|
426
|
+
</ConfigProvider>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 8. App Component - message/notification/modal
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
// ❌ WRONG: Direct import (won't respect ConfigProvider)
|
|
433
|
+
import { message } from 'antd';
|
|
434
|
+
message.success('Done!');
|
|
435
|
+
|
|
436
|
+
// ✅ CORRECT: Use App.useApp() hook
|
|
437
|
+
import { App } from 'antd';
|
|
438
|
+
|
|
439
|
+
function MyComponent() {
|
|
440
|
+
const { message, notification, modal } = App.useApp();
|
|
441
|
+
|
|
442
|
+
const handleClick = () => {
|
|
443
|
+
message.success('Done!'); // Respects ConfigProvider theme
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Wrap your app with App component
|
|
448
|
+
<ConfigProvider theme={...}>
|
|
449
|
+
<App>
|
|
450
|
+
<YourApp />
|
|
451
|
+
</App>
|
|
452
|
+
</ConfigProvider>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### 9. Icons - Named imports required
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
// ❌ WRONG: Default import
|
|
459
|
+
import Icon from '@ant-design/icons';
|
|
460
|
+
<Icon type="user" />
|
|
461
|
+
|
|
462
|
+
// ✅ CORRECT: Named imports
|
|
463
|
+
import { UserOutlined, EditOutlined } from '@ant-design/icons';
|
|
464
|
+
<UserOutlined />
|
|
465
|
+
<EditOutlined />
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 10. Grid - `xs`, `sm`, etc. as objects
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
// ❌ CAREFUL: Mixing number and object syntax
|
|
472
|
+
<Col xs={24} sm={{ span: 12, offset: 6 }}>
|
|
473
|
+
|
|
474
|
+
// ✅ PREFERRED: Be consistent
|
|
475
|
+
<Col xs={{ span: 24 }} sm={{ span: 12, offset: 6 }}>
|
|
476
|
+
// OR
|
|
477
|
+
<Col xs={24} sm={12}>
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## Anti-Patterns
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
// ❌ Creating components that Ant Design already has
|
|
486
|
+
function CustomButton({ children }) { ... } // Use <Button> from antd
|
|
487
|
+
function CustomModal({ visible }) { ... } // Use <Modal> from antd
|
|
488
|
+
function CustomTable({ data }) { ... } // Use <Table> from antd
|
|
489
|
+
function DataGrid({ rows }) { ... } // Use <Table> from antd
|
|
490
|
+
|
|
491
|
+
// ❌ Installing libraries without permission
|
|
492
|
+
npm install lodash // Ask first!
|
|
493
|
+
npm install react-icons // Use @ant-design/icons
|
|
494
|
+
npm install styled-components // Use Tailwind CSS
|
|
495
|
+
|
|
496
|
+
// ❌ API call in component (bypass service layer)
|
|
497
|
+
function UserList() {
|
|
498
|
+
const { data } = useQuery({
|
|
499
|
+
queryKey: ["users"],
|
|
500
|
+
queryFn: () => axios.get("/api/users"), // WRONG: Use service
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ❌ Business logic in component
|
|
505
|
+
function UserList() {
|
|
506
|
+
const users = data?.filter(u => u.active).sort((a, b) => a.name > b.name);
|
|
507
|
+
// Move to service or utility function
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ❌ Hardcoded strings - use i18n
|
|
511
|
+
<Button>Save</Button> // WRONG
|
|
512
|
+
<Button>{t("common.save")}</Button> // CORRECT
|
|
513
|
+
|
|
514
|
+
// ❌ Multiple sources of truth
|
|
515
|
+
const [users, setUsers] = useState([]); // Local state
|
|
516
|
+
const { data } = useQuery({ ... }); // Server state
|
|
517
|
+
// Pick one: TanStack Query for server data
|
|
518
|
+
|
|
519
|
+
// ❌ Prop drilling
|
|
520
|
+
<Parent data={data}>
|
|
521
|
+
<Child data={data}>
|
|
522
|
+
<GrandChild data={data} /> // Use Context or pass minimal props
|
|
523
|
+
</Child>
|
|
524
|
+
</Parent>
|
|
525
|
+
|
|
526
|
+
// ❌ Giant components (>200 lines)
|
|
527
|
+
// Split into smaller components or extract hooks
|
|
528
|
+
```
|