@openway/ui 1.0.0 → 1.0.1
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 +203 -181
- package/dist/chunk-CJQNI3QX.js +3 -0
- package/dist/chunk-CJQNI3QX.js.map +1 -0
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2642 -1103
- package/dist/index.d.ts +2642 -1103
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/query.cjs +3 -0
- package/dist/query.cjs.map +1 -0
- package/dist/query.d.cts +309 -0
- package/dist/query.d.ts +309 -0
- package/dist/query.js +3 -0
- package/dist/query.js.map +1 -0
- package/dist/useInfiniteScroll-DAlgjUN4.d.cts +325 -0
- package/dist/useInfiniteScroll-DAlgjUN4.d.ts +325 -0
- package/docs/AGENTS.md +144 -0
- package/docs/README.md +150 -0
- package/docs/SKILL.md +54 -0
- package/docs/components/alert.md +246 -0
- package/docs/components/badge.md +238 -0
- package/docs/components/button.md +262 -0
- package/docs/components/carousel.md +354 -0
- package/docs/components/checkbox.md +252 -0
- package/docs/components/collapse.md +318 -0
- package/docs/components/confirm.md +322 -0
- package/docs/components/datepicker.md +259 -0
- package/docs/components/daterangepicker.md +260 -0
- package/docs/components/datetimepicker.md +226 -0
- package/docs/components/datetimerangepicker.md +222 -0
- package/docs/components/dropdown.md +275 -0
- package/docs/components/empty.md +200 -0
- package/docs/components/file-preview.md +180 -0
- package/docs/components/input.md +559 -0
- package/docs/components/modal.md +293 -0
- package/docs/components/popover.md +255 -0
- package/docs/components/radio.md +245 -0
- package/docs/components/select.md +254 -0
- package/docs/components/skeleton.md +150 -0
- package/docs/components/slider.md +346 -0
- package/docs/components/table.md +316 -0
- package/docs/components/tabs.md +432 -0
- package/docs/components/textarea.md +193 -0
- package/docs/components/timepicker.md +242 -0
- package/docs/components/timerangepicker.md +210 -0
- package/docs/components/toast.md +282 -0
- package/docs/components/toggle.md +211 -0
- package/docs/components/tooltip.md +213 -0
- package/docs/components/upload-avatar.md +318 -0
- package/docs/components/upload-file.md +245 -0
- package/docs/components/upload-image.md +126 -0
- package/docs/hooks/useDebounce.md +92 -0
- package/docs/hooks/useInfiniteScroll.md +95 -0
- package/docs/hooks/useSelectInfiniteQuery.md +123 -0
- package/docs/hooks/useTableQuery.md +124 -0
- package/package.json +31 -12
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# 🏷️ Badge Component (`@owa/ui`)
|
|
2
|
+
|
|
3
|
+
Component **Badge** (Huy hiệu / Nhãn trạng thái / Chip) hiệu năng cao, thiết kế chuẩn **Design System**, **Pure Stateless Component** (0 dependencies) và hỗ trợ đầy đủ **WAI-ARIA Accessibility**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🌟 Điểm nổi bật
|
|
8
|
+
|
|
9
|
+
- **Pure Stateless Component**: Render nhanh chóng, không phụ thuộc vào global store, dễ dàng sử dụng ở bất kỳ đâu trong JSX.
|
|
10
|
+
- **5 Kích thước tiêu chuẩn (`size`)**: `xs` (20px), `sm` (24px), `md` (28px - *mặc định*), `lg` (32px), `xl` (36px) với typography, padding và kích thước icon tự động căn chỉnh đồng bộ.
|
|
11
|
+
- **5 Biến thể giao diện (`variant`)**:
|
|
12
|
+
- `soft` *(mặc định)*: Nền pastel nhạt, chữ đậm, viền mờ 1px nhẹ nhàng, tinh tế.
|
|
13
|
+
- `filled`: Nền màu đậm, độ tương phản cao, chữ trắng nổi bật.
|
|
14
|
+
- `outline`: Nền trong suốt, viền đôi 2px rõ nét theo màu chủ đề.
|
|
15
|
+
- `ghost`: Không viền, nền trong suốt, đổi màu nhẹ khi hover.
|
|
16
|
+
- `other`: Bỏ qua các class màu mặc định, tự do tùy biến màu sắc / gradient qua `className`.
|
|
17
|
+
- **7 Chủ đề màu sắc (`color`)**: `primary`, `secondary`, `error`, `success`, `warning`, `info`, `neutral`.
|
|
18
|
+
- **Tùy chỉnh bo góc linh hoạt (`radius`)**: `none` (góc vuông), `sm`, `md`, `lg`, `xl`, `full` (*mặc định* - kiểu dáng viên thuốc Pill).
|
|
19
|
+
- **Chấm trạng thái (Status Dot & Radar Ping)**:
|
|
20
|
+
- `dot={true}`: Hiển thị chấm tròn trạng thái đồng bộ màu sắc.
|
|
21
|
+
- `dotPing={true}`: Bật hiệu ứng radar pulse nhấp nháy sinh động (thích hợp cho Live Stream, Trạng thái online, Cảnh báo nguy cấp).
|
|
22
|
+
- **Hỗ trợ Icon trước & sau (`leftIcon`, `rightIcon`)**: Tự động scale kích thước icon tương ứng theo `size` của badge.
|
|
23
|
+
- **Chế độ Dismissible Chip (`onDelete`)**: Tích hợp sẵn nút xóa/gỡ bỏ `(X)` với hiệu ứng hover và nhãn trợ năng `deleteAriaLabel`.
|
|
24
|
+
- **Tương tác Click (`onClick`)**: Tự động chuyển đổi thành nút bấm tương tác (`role="button"`, `tabIndex={0}`), kèm hiệu ứng nhấn `active:scale-[0.98]` mượt mà.
|
|
25
|
+
- **Safe Config Fallback**: Tích hợp hàm `getSafeConfig` đảm bảo component luôn an toàn, không bị crash dù truyền giá trị `size`, `variant`, `color`, `radius` không hợp lệ.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🚀 Cài đặt & Import
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Badge } from "@owa/ui";
|
|
33
|
+
import type { BadgeProps, BadgeSize, BadgeVariant, BadgeColor, BadgeRadius } from "@owa/ui";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 📖 Hướng dẫn sử dụng
|
|
39
|
+
|
|
40
|
+
### 1. Cách sử dụng cơ bản
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { Badge } from "@owa/ui";
|
|
44
|
+
|
|
45
|
+
export function BasicBadgeExample() {
|
|
46
|
+
return (
|
|
47
|
+
<div className="flex gap-2 items-center">
|
|
48
|
+
<Badge>Mặc định</Badge>
|
|
49
|
+
<Badge color="success">Hoàn thành</Badge>
|
|
50
|
+
<Badge color="warning" variant="filled">Cảnh báo</Badge>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### 2. Các kích thước (`size`)
|
|
59
|
+
|
|
60
|
+
Hỗ trợ 5 kích thước chuẩn: `xs`, `sm`, `md` *(mặc định)*, `lg`, `xl`.
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<Badge size="xs">Extra Small (20px)</Badge>
|
|
64
|
+
<Badge size="sm">Small (24px)</Badge>
|
|
65
|
+
<Badge size="md">Medium (28px)</Badge>
|
|
66
|
+
<Badge size="lg">Large (32px)</Badge>
|
|
67
|
+
<Badge size="xl">Extra Large (36px)</Badge>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### 3. Các biến thể giao diện (`variant`)
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// 1. Soft (Mặc định): Nền pastel nhạt
|
|
76
|
+
<Badge variant="soft" color="primary">Soft Primary</Badge>
|
|
77
|
+
|
|
78
|
+
// 2. Filled: Nền đậm, độ tương phản cao
|
|
79
|
+
<Badge variant="filled" color="primary">Filled Primary</Badge>
|
|
80
|
+
|
|
81
|
+
// 3. Outline: Nền trong suốt, viền 2px
|
|
82
|
+
<Badge variant="outline" color="primary">Outline Primary</Badge>
|
|
83
|
+
|
|
84
|
+
// 4. Ghost: Nền trong suốt, không viền
|
|
85
|
+
<Badge variant="ghost" color="primary">Ghost Primary</Badge>
|
|
86
|
+
|
|
87
|
+
// 5. Other: Tự do tùy biến 100% bằng Tailwind
|
|
88
|
+
<Badge
|
|
89
|
+
variant="other"
|
|
90
|
+
className="bg-linear-to-r from-violet-600 to-pink-500 text-white shadow-sm border-0"
|
|
91
|
+
>
|
|
92
|
+
Gradient VIP
|
|
93
|
+
</Badge>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### 4. Các chủ đề màu sắc (`color`)
|
|
99
|
+
|
|
100
|
+
Cung cấp 7 tông màu theo chuẩn Design System:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
<Badge color="primary">Primary</Badge>
|
|
104
|
+
<Badge color="secondary">Secondary</Badge>
|
|
105
|
+
<Badge color="success">Success</Badge>
|
|
106
|
+
<Badge color="error">Error</Badge>
|
|
107
|
+
<Badge color="warning">Warning</Badge>
|
|
108
|
+
<Badge color="info">Info</Badge>
|
|
109
|
+
<Badge color="neutral">Neutral</Badge>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 5. Chấm trạng thái (Status Dot & Radar Ping)
|
|
115
|
+
|
|
116
|
+
Thích hợp hiển thị trạng thái tài khoản, server, tiến trình:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
// Chấm trạng thái tĩnh
|
|
120
|
+
<Badge dot color="success">Online</Badge>
|
|
121
|
+
<Badge dot color="neutral">Offline</Badge>
|
|
122
|
+
<Badge dot color="warning">Pending</Badge>
|
|
123
|
+
|
|
124
|
+
// Chấm trạng thái nhấp nháy (Radar Pulse Ping)
|
|
125
|
+
<Badge dot dotPing color="error">Live 2.4k</Badge>
|
|
126
|
+
<Badge dot dotPing color="primary" variant="filled">Stream Active</Badge>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### 6. Icon trước & sau (`leftIcon`, `rightIcon`)
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { Badge } from "@owa/ui";
|
|
135
|
+
import { SparklesIcon, CheckIcon, ShieldIcon } from "@/components/icons";
|
|
136
|
+
|
|
137
|
+
export function IconBadgeExample() {
|
|
138
|
+
return (
|
|
139
|
+
<div className="flex gap-2">
|
|
140
|
+
<Badge color="primary" leftIcon={<SparklesIcon />}>
|
|
141
|
+
Đặc quyền VIP
|
|
142
|
+
</Badge>
|
|
143
|
+
<Badge color="success" rightIcon={<CheckIcon />}>
|
|
144
|
+
Đã xác minh
|
|
145
|
+
</Badge>
|
|
146
|
+
<Badge color="secondary" leftIcon={<ShieldIcon />} rightIcon={<CheckIcon />}>
|
|
147
|
+
Bảo mật cao
|
|
148
|
+
</Badge>
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### 7. Dismissible Chip (Có nút xóa `onDelete`)
|
|
157
|
+
|
|
158
|
+
Khi truyền prop `onDelete`, Badge sẽ hiển thị nút đóng `(X)` ở góc phải:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { useState } from "react";
|
|
162
|
+
import { Badge } from "@owa/ui";
|
|
163
|
+
|
|
164
|
+
export function ChipListExample() {
|
|
165
|
+
const [tags, setTags] = useState(["React", "TypeScript", "TailwindCSS"]);
|
|
166
|
+
|
|
167
|
+
const removeTag = (tagToRemove: string) => {
|
|
168
|
+
setTags(tags.filter((tag) => tag !== tagToRemove));
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<div className="flex gap-2 flex-wrap">
|
|
173
|
+
{tags.map((tag) => (
|
|
174
|
+
<Badge
|
|
175
|
+
key={tag}
|
|
176
|
+
color="primary"
|
|
177
|
+
onDelete={() => removeTag(tag)}
|
|
178
|
+
deleteAriaLabel={`Xóa thẻ ${tag}`}
|
|
179
|
+
>
|
|
180
|
+
{tag}
|
|
181
|
+
</Badge>
|
|
182
|
+
))}
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### 8. Tương tác bấm (`onClick`)
|
|
191
|
+
|
|
192
|
+
Badge tự động hỗ trợ cursor pointer, hiệu ứng `active:scale-[0.98]`, `role="button"` và `tabIndex={0}`:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<Badge
|
|
196
|
+
color="info"
|
|
197
|
+
variant="soft"
|
|
198
|
+
onClick={() => alert("Đã chọn bộ lọc!")}
|
|
199
|
+
>
|
|
200
|
+
Bộ lọc: Mới nhất
|
|
201
|
+
</Badge>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### 9. Tùy chỉnh bo góc (`radius`)
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
<Badge radius="none">radius="none" (0px)</Badge>
|
|
210
|
+
<Badge radius="sm">radius="sm" (rounded-sm)</Badge>
|
|
211
|
+
<Badge radius="md">radius="md" (rounded-md)</Badge>
|
|
212
|
+
<Badge radius="lg">radius="lg" (rounded-lg)</Badge>
|
|
213
|
+
<Badge radius="xl">radius="xl" (rounded-xl)</Badge>
|
|
214
|
+
<Badge radius="full">radius="full" (Pill - Mặc định)</Badge>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 🛠️ API Reference (`BadgeProps`)
|
|
220
|
+
|
|
221
|
+
Component `Badge` nhận các props mở rộng từ thẻ HTML chuẩn `HTMLAttributes<HTMLSpanElement>`:
|
|
222
|
+
|
|
223
|
+
| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
|
|
224
|
+
| :--- | :--- | :--- | :--- |
|
|
225
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Kích cỡ của badge (ảnh hưởng chiều cao, padding, font size, icon size). |
|
|
226
|
+
| `variant` | `"soft" \| "filled" \| "outline" \| "ghost" \| "other"` | `"soft"` | Biến thể giao diện và phong cách hiển thị màu sắc. |
|
|
227
|
+
| `color` | `"primary" \| "secondary" \| "error" \| "success" \| "warning" \| "info" \| "neutral"` | `"primary"` | Chủ đề màu sắc theo Design System. |
|
|
228
|
+
| `radius` | `"none" \| "sm" \| "md" \| "lg" \| "xl" \| "full"` | `"full"` | Độ bo góc của badge. |
|
|
229
|
+
| `dot` | `boolean` | `false` | Hiển thị chấm tròn trạng thái ở đầu badge. |
|
|
230
|
+
| `dotPing` | `boolean` | `false` | Bật hiệu ứng nhấp nháy (pulse) cho chấm tròn trạng thái. |
|
|
231
|
+
| `leftIcon` | `ReactNode` | `undefined` | Icon hoặc phần tử hiển thị phía trước nội dung. |
|
|
232
|
+
| `rightIcon` | `ReactNode` | `undefined` | Icon hoặc phần tử hiển thị phía sau nội dung (ẩn khi có `onDelete`). |
|
|
233
|
+
| `onDelete` | `() => void` | `undefined` | Callback khi người dùng bấm nút xóa `(X)` trên badge. |
|
|
234
|
+
| `deleteAriaLabel` | `string` | `"Remove"` | Nhãn trợ năng (accessibility) cho nút xóa `(X)`. |
|
|
235
|
+
| `children` | `ReactNode` | `undefined` | Nội dung văn bản hoặc phần tử hiển thị bên trong badge. |
|
|
236
|
+
| `onClick` | `MouseEventHandler<HTMLSpanElement>` | `undefined` | Sự kiện click biến badge thành nút tương tác. |
|
|
237
|
+
| `className` | `string` | `""` | Class CSS Tailwind tùy biến bên ngoài. |
|
|
238
|
+
| `ref` | `Ref<HTMLSpanElement>` | `undefined` | Ref chuyển tiếp đến thẻ `<span>` của badge. |
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# 🔘 Button & IconButton Component (`@owa/ui`)
|
|
2
|
+
|
|
3
|
+
Bộ component **Button** & **IconButton** tương tác cao, thiết kế chuẩn **Design System**, hỗ trợ **trạng thái Loading linh hoạt**, **Safe Config Fallback** và tuân thủ đầy đủ tiêu chuẩn **WAI-ARIA Accessibility**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🌟 Điểm nổi bật
|
|
8
|
+
|
|
9
|
+
- **Pure Stateless & Hiệu năng cao**: Tối ưu hóa render, không phụ thuộc vào global store, dễ dàng sử dụng và mở rộng.
|
|
10
|
+
- **2 Biến thể Component tiện dụng**:
|
|
11
|
+
- `<Button>`: Nút bấm tiêu chuẩn kèm văn bản, icon trái/phải, chế độ full width.
|
|
12
|
+
- `<IconButton>`: Nút bấm chỉ chứa icon hình tròn / vuông, bắt buộc nhãn `aria-label` cho trợ năng (Screen Reader).
|
|
13
|
+
- **5 Kích thước tiêu chuẩn (`size`)**: `xs` (24px), `sm` (32px), `md` (40px - *mặc định*), `lg` (48px), `xl` (56px) với chiều cao, padding, font size và kích cỡ icon được căn chuẩn theo tỷ lệ.
|
|
14
|
+
- **6 Biến thể giao diện (`variant`)**:
|
|
15
|
+
- `filled` *(mặc định)*: Nền màu đậm, chữ trắng tương phản cao, nổi bật các hành động chính (Primary CTA).
|
|
16
|
+
- `soft`: Nền pastel nhạt, chữ và viền cùng tông màu, thích hợp cho hành động phụ.
|
|
17
|
+
- `outline`: Nền trong suốt, viền đôi 2px rõ nét, hover đổi màu nền nhẹ.
|
|
18
|
+
- `ghost`: Nền và viền trong suốt, hiển thị nền khi hover.
|
|
19
|
+
- `text`: Nút dạng chữ không viền, padding hẹp, hover đổi màu chữ.
|
|
20
|
+
- `other`: Bỏ qua các class màu mặc định, tự do áp dụng custom style / gradient qua `className`.
|
|
21
|
+
- **7 Chủ đề màu sắc (`color`)**: `primary`, `secondary`, `neutral`, `error`, `success`, `warning`, `info`.
|
|
22
|
+
- **Tùy chỉnh bo góc linh hoạt (`radius`)**: `none` (góc vuông 0px), `sm`, `md`, `lg` (*mặc định trên Button*), `xl`, `full` (*mặc định trên IconButton*).
|
|
23
|
+
- **Trạng thái Loading thông minh (`isLoading` & `showSpinner`)**:
|
|
24
|
+
- `isLoading={true}`: Tự động khóa tương tác (`disabled`), đặt `aria-busy="true"` và `aria-disabled="true"`.
|
|
25
|
+
- `showSpinner`: Mặc định là `false` (không hiển thị spinner xoay). Đặt `showSpinner={true}` khi muốn hiển thị icon xoay vòng.
|
|
26
|
+
- `loadingText`: Cho phép thay thế nội dung hiển thị khi đang tải (ví dụ: *"Đang xử lý..."*).
|
|
27
|
+
- **Trải nghiệm tương tác mượt mà**: Hiệu ứng thu nhỏ nhẹ khi bấm (`active:scale-[0.98]`), focus ring shade 700 nổi bật khi điều hướng bằng bàn phím.
|
|
28
|
+
- **Safe Config Fallback**: Tích hợp hàm `getSafeConfig` đảm bảo component hoạt động ổn định, không bị crash kể cả khi truyền prop kích cỡ/màu sắc không hợp lệ.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Cài đặt & Import
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { Button, IconButton } from "@owa/ui";
|
|
36
|
+
import type {
|
|
37
|
+
ButtonProps,
|
|
38
|
+
IconButtonProps,
|
|
39
|
+
ButtonSize,
|
|
40
|
+
ButtonVariant,
|
|
41
|
+
ButtonColor,
|
|
42
|
+
ButtonRadius,
|
|
43
|
+
} from "@owa/ui";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 📖 Hướng dẫn sử dụng
|
|
49
|
+
|
|
50
|
+
### 1. Cách sử dụng cơ bản
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { Button } from "@owa/ui";
|
|
54
|
+
|
|
55
|
+
export function BasicButtonExample() {
|
|
56
|
+
return (
|
|
57
|
+
<div className="flex gap-3 items-center">
|
|
58
|
+
<Button>Button Mặc định</Button>
|
|
59
|
+
<Button color="secondary">Secondary</Button>
|
|
60
|
+
<Button color="success" variant="soft">Lưu thay đổi</Button>
|
|
61
|
+
<Button color="error" variant="outline">Xóa dữ liệu</Button>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### 2. Các kích thước (`size`)
|
|
70
|
+
|
|
71
|
+
Hỗ trợ 5 kích thước từ `xs` đến `xl`:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<Button size="xs">Extra Small (24px)</Button>
|
|
75
|
+
<Button size="sm">Small (32px)</Button>
|
|
76
|
+
<Button size="md">Medium (40px - Mặc định)</Button>
|
|
77
|
+
<Button size="lg">Large (48px)</Button>
|
|
78
|
+
<Button size="xl">Extra Large (56px)</Button>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### 3. Các biến thể giao diện (`variant`)
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// 1. Filled (Mặc định): Nền đậm nổi bật
|
|
87
|
+
<Button variant="filled" color="primary">Filled Primary</Button>
|
|
88
|
+
|
|
89
|
+
// 2. Soft: Nền pastel nhạt
|
|
90
|
+
<Button variant="soft" color="primary">Soft Primary</Button>
|
|
91
|
+
|
|
92
|
+
// 3. Outline: Viền 2px
|
|
93
|
+
<Button variant="outline" color="primary">Outline Primary</Button>
|
|
94
|
+
|
|
95
|
+
// 4. Ghost: Nền trong suốt
|
|
96
|
+
<Button variant="ghost" color="primary">Ghost Primary</Button>
|
|
97
|
+
|
|
98
|
+
// 5. Text: Dạng văn bản tối giản
|
|
99
|
+
<Button variant="text" color="primary">Text Button</Button>
|
|
100
|
+
|
|
101
|
+
// 6. Other: Tự do tùy biến 100% qua className
|
|
102
|
+
<Button
|
|
103
|
+
variant="other"
|
|
104
|
+
className="bg-linear-to-r from-violet-600 via-purple-600 to-pink-500 text-white shadow-md hover:opacity-90"
|
|
105
|
+
>
|
|
106
|
+
Gradient VIP
|
|
107
|
+
</Button>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### 4. Các chủ đề màu sắc (`color`)
|
|
113
|
+
|
|
114
|
+
Cung cấp 7 tông màu theo chuẩn Design System:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<Button color="primary">Primary</Button>
|
|
118
|
+
<Button color="secondary">Secondary</Button>
|
|
119
|
+
<Button color="neutral">Neutral</Button>
|
|
120
|
+
<Button color="error">Error</Button>
|
|
121
|
+
<Button color="success">Success</Button>
|
|
122
|
+
<Button color="warning">Warning</Button>
|
|
123
|
+
<Button color="info">Info</Button>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### 5. Hỗ trợ Icon (`leftIcon`, `rightIcon`) & Component `<IconButton>`
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { Button, IconButton } from "@owa/ui";
|
|
132
|
+
import { PlusIcon, ArrowRightIcon, TrashIcon, HeartIcon } from "@/components/icons";
|
|
133
|
+
|
|
134
|
+
export function ButtonIconExample() {
|
|
135
|
+
return (
|
|
136
|
+
<div className="space-y-4">
|
|
137
|
+
{/* Button có icon đầu hoặc cuối */}
|
|
138
|
+
<div className="flex gap-3 items-center">
|
|
139
|
+
<Button leftIcon={<PlusIcon />}>Tạo mới</Button>
|
|
140
|
+
<Button variant="outline" color="secondary" rightIcon={<ArrowRightIcon />}>
|
|
141
|
+
Tiếp tục
|
|
142
|
+
</Button>
|
|
143
|
+
<Button variant="ghost" color="error" leftIcon={<TrashIcon />}>
|
|
144
|
+
Xóa
|
|
145
|
+
</Button>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
{/* IconButton tròn chuyên dụng */}
|
|
149
|
+
<div className="flex gap-3 items-center">
|
|
150
|
+
<IconButton icon={<HeartIcon />} aria-label="Yêu thích" color="error" variant="soft" />
|
|
151
|
+
<IconButton icon={<PlusIcon />} aria-label="Thêm mới" color="primary" variant="filled" />
|
|
152
|
+
<IconButton icon={<TrashIcon />} aria-label="Xóa mục" color="neutral" variant="ghost" />
|
|
153
|
+
{/* Tùy chỉnh bo góc cho IconButton */}
|
|
154
|
+
<IconButton icon={<PlusIcon />} aria-label="Thêm" radius="md" variant="outline" />
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### 6. Trạng thái Loading & Tùy chọn Spinner (`isLoading`, `showSpinner`, `loadingText`)
|
|
164
|
+
|
|
165
|
+
Khi `isLoading={true}`, nút sẽ tự động bị vô hiệu hóa (`disabled`), đặt `aria-busy="true"`. Bạn có thể tùy chọn có hiển thị icon xoay vòng hay không thông qua prop `showSpinner` (mặc định là `false`):
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
// 1. Loading không hiện spinner (mặc định: showSpinner=false)
|
|
169
|
+
<Button isLoading>Đang lưu...</Button>
|
|
170
|
+
|
|
171
|
+
// 2. Loading có hiện spinner xoay vòng (showSpinner=true)
|
|
172
|
+
<Button isLoading showSpinner>Đang lưu...</Button>
|
|
173
|
+
|
|
174
|
+
// 3. Loading có spinner kèm theo loadingText thay thế
|
|
175
|
+
<Button isLoading showSpinner loadingText="Đang xử lý dữ liệu...">
|
|
176
|
+
Gửi yêu cầu
|
|
177
|
+
</Button>
|
|
178
|
+
|
|
179
|
+
// 4. IconButton ở trạng thái loading
|
|
180
|
+
<IconButton
|
|
181
|
+
icon={<TrashIcon />}
|
|
182
|
+
aria-label="Đang xóa"
|
|
183
|
+
isLoading
|
|
184
|
+
showSpinner
|
|
185
|
+
/>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### 7. Tràn chiều rộng (`isFullWidth`) & Vô hiệu hóa (`disabled`)
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
// Chiều rộng 100% của container
|
|
194
|
+
<Button isFullWidth color="primary" size="lg">
|
|
195
|
+
Đăng ký tài khoản ngay
|
|
196
|
+
</Button>
|
|
197
|
+
|
|
198
|
+
// Nút bị vô hiệu hóa
|
|
199
|
+
<Button disabled color="primary">
|
|
200
|
+
Không khả dụng
|
|
201
|
+
</Button>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### 8. Tùy chỉnh bo góc (`radius`)
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
<Button radius="none">radius="none" (0px)</Button>
|
|
210
|
+
<Button radius="sm">radius="sm" (rounded-sm)</Button>
|
|
211
|
+
<Button radius="md">radius="md" (rounded-md)</Button>
|
|
212
|
+
<Button radius="lg">radius="lg" (rounded-lg - Mặc định)</Button>
|
|
213
|
+
<Button radius="xl">radius="xl" (rounded-xl)</Button>
|
|
214
|
+
<Button radius="full">radius="full" (Pill Shape)</Button>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 🛠️ API Reference
|
|
220
|
+
|
|
221
|
+
### 1. `ButtonProps`
|
|
222
|
+
|
|
223
|
+
Kế thừa toàn bộ thuộc tính chuẩn của thẻ HTML `<button>` (`ButtonHTMLAttributes<HTMLButtonElement>`):
|
|
224
|
+
|
|
225
|
+
| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
|
|
226
|
+
| :--- | :--- | :--- | :--- |
|
|
227
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Kích cỡ của nút (chiều cao, padding, font size, icon size). |
|
|
228
|
+
| `variant` | `"filled" \| "soft" \| "ghost" \| "text" \| "outline" \| "other"` | `"filled"` | Biến thể giao diện và phong cách màu sắc. |
|
|
229
|
+
| `color` | `"primary" \| "secondary" \| "neutral" \| "error" \| "success" \| "warning" \| "info"` | `"primary"` | Chủ đề màu sắc theo Design System. |
|
|
230
|
+
| `radius` | `"none" \| "sm" \| "md" \| "lg" \| "xl" \| "full"` | `"lg"` | Độ bo góc của nút bấm. |
|
|
231
|
+
| `leftIcon` | `ReactNode` | `undefined` | Icon hoặc phần tử hiển thị trước nội dung chữ. |
|
|
232
|
+
| `rightIcon` | `ReactNode` | `undefined` | Icon hoặc phần tử hiển thị sau nội dung chữ. |
|
|
233
|
+
| `isLoading` | `boolean` | `false` | Trạng thái đang tải (tự động khóa tương tác và đặt aria-busy). |
|
|
234
|
+
| `showSpinner` | `boolean` | `false` | Hiển thị biểu tượng xoay spinner khi đang ở trạng thái loading. |
|
|
235
|
+
| `loadingText` | `ReactNode` | `undefined` | Văn bản hiển thị thay thế khi đang loading. |
|
|
236
|
+
| `isFullWidth` | `boolean` | `false` | Mở rộng chiều rộng chiếm 100% khung chứa (`w-full`). |
|
|
237
|
+
| `disabled` | `boolean` | `false` | Vô hiệu hóa nút bấm. |
|
|
238
|
+
| `children` | `ReactNode` | `undefined` | Nội dung văn bản hoặc phần tử bên trong nút. |
|
|
239
|
+
| `type` | `"button" \| "submit" \| "reset"` | `"button"` | Thuộc tính type chuẩn của HTML button. |
|
|
240
|
+
| `className` | `string` | `""` | Class CSS Tailwind tùy biến bên ngoài. |
|
|
241
|
+
| `ref` | `Ref<HTMLButtonElement>` | `undefined` | Ref chuyển tiếp đến thẻ `<button>`. |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### 2. `IconButtonProps`
|
|
246
|
+
|
|
247
|
+
Kế thừa các thuộc tính của `<button>` ngoại trừ `children`:
|
|
248
|
+
|
|
249
|
+
| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
|
|
250
|
+
| :--- | :--- | :--- | :--- |
|
|
251
|
+
| `icon` | `ReactNode` | *(Bắt buộc)* | Icon hiển thị chính giữa nút. |
|
|
252
|
+
| `aria-label` | `string` | *(Bắt buộc)* | Nhãn mô tả hành động dành cho Screen Reader / A11y. |
|
|
253
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Kích cỡ của nút icon (24px, 32px, 40px, 48px, 56px). |
|
|
254
|
+
| `variant` | `"filled" \| "soft" \| "ghost" \| "text" \| "outline" \| "other"` | `"filled"` | Biến thể giao diện của nút icon. |
|
|
255
|
+
| `color` | `"primary" \| "secondary" \| "neutral" \| "error" \| "success" \| "warning" \| "info"` | `"primary"` | Chủ đề màu sắc theo Design System. |
|
|
256
|
+
| `radius` | `"none" \| "sm" \| "md" \| "lg" \| "xl" \| "full"` | `"full"` | Độ bo góc của nút icon (mặc định tròn hoàn toàn). |
|
|
257
|
+
| `isLoading` | `boolean` | `false` | Trạng thái đang tải (vô hiệu hóa tương tác). |
|
|
258
|
+
| `showSpinner` | `boolean` | `false` | Hiển thị spinner xoay thay thế cho icon khi đang loading. |
|
|
259
|
+
| `disabled` | `boolean` | `false` | Vô hiệu hóa nút icon. |
|
|
260
|
+
| `type` | `"button" \| "submit" \| "reset"` | `"button"` | Thuộc tính type của nút. |
|
|
261
|
+
| `className` | `string` | `""` | Class CSS Tailwind tùy biến bên ngoài. |
|
|
262
|
+
| `ref` | `Ref<HTMLButtonElement>` | `undefined` | Ref chuyển tiếp đến thẻ `<button>`. |
|