@a2v2ai/uikit 0.0.39 → 0.0.40

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.
Files changed (182) hide show
  1. package/Alert/Alert.stories.tsx +121 -0
  2. package/Alert/Alert.tsx +71 -0
  3. package/AlertDialog/AlertDialog.stories.tsx +665 -0
  4. package/AlertDialog/AlertDialog.tsx +241 -0
  5. package/Avatar/Avatar.stories.tsx +128 -0
  6. package/Avatar/Avatar.tsx +71 -0
  7. package/Badge/Badge.stories.tsx +76 -0
  8. package/Badge/Badge.tsx +39 -0
  9. package/Breadcrumb/Breadcrumb.stories.tsx +231 -0
  10. package/Breadcrumb/Breadcrumb.tsx +114 -0
  11. package/Button/Button.stories.tsx +684 -0
  12. package/Button/Button.tsx +107 -0
  13. package/Calendar/Calendar.stories.tsx +291 -0
  14. package/Calendar/Calendar.tsx +246 -0
  15. package/Card/Card.stories.tsx +136 -0
  16. package/Card/Card.tsx +96 -0
  17. package/Carousel/Carousel.stories.tsx +256 -0
  18. package/Carousel/Carousel.tsx +301 -0
  19. package/ChatBubble/ChatBubble.stories.tsx +339 -0
  20. package/ChatBubble/ChatBubble.tsx +179 -0
  21. package/Checkbox/Checkbox.stories.tsx +137 -0
  22. package/Checkbox/Checkbox.tsx +53 -0
  23. package/DataTable/DataTable.stories.tsx +400 -0
  24. package/DataTable/DataTable.tsx +207 -0
  25. package/Drawer/Drawer.stories.tsx +721 -0
  26. package/Drawer/Drawer.tsx +201 -0
  27. package/DropdownMenu/DropdownMenu.stories.tsx +251 -0
  28. package/DropdownMenu/DropdownMenu.tsx +199 -0
  29. package/ErrorMessage/ErrorMessage.stories.tsx +159 -0
  30. package/ErrorMessage/ErrorMessage.tsx +55 -0
  31. package/Flex/Flex.stories.tsx +390 -0
  32. package/Flex/Flex.tsx +102 -0
  33. package/IconButton/IconButton.stories.tsx +566 -0
  34. package/IconButton/IconButton.tsx +95 -0
  35. package/Input/Input.stories.tsx +566 -0
  36. package/Input/Input.tsx +168 -0
  37. package/InputOTP/InputOTP.stories.tsx +246 -0
  38. package/InputOTP/InputOTP.tsx +127 -0
  39. package/Label/Label.stories.tsx +110 -0
  40. package/Label/Label.tsx +44 -0
  41. package/Loader/Loader.stories.tsx +170 -0
  42. package/Loader/Loader.tsx +62 -0
  43. package/Menubar/Menubar.stories.tsx +382 -0
  44. package/Menubar/Menubar.tsx +274 -0
  45. package/Menubar/index.ts +18 -0
  46. package/Pagination/Pagination.stories.tsx +196 -0
  47. package/Pagination/Pagination.tsx +122 -0
  48. package/Popover/Popover.stories.tsx +133 -0
  49. package/Popover/Popover.tsx +31 -0
  50. package/Progress/Progress.stories.tsx +146 -0
  51. package/Progress/Progress.tsx +67 -0
  52. package/RadioGroup/RadioGroup.stories.tsx +159 -0
  53. package/RadioGroup/RadioGroup.tsx +68 -0
  54. package/ScrollArea/ScrollArea.stories.tsx +136 -0
  55. package/ScrollArea/ScrollArea.tsx +46 -0
  56. package/Select/Select.stories.tsx +378 -0
  57. package/Select/Select.tsx +230 -0
  58. package/Separator/Separator.stories.tsx +110 -0
  59. package/Separator/Separator.tsx +29 -0
  60. package/Sidebar/Sidebar.stories.tsx +340 -0
  61. package/Sidebar/Sidebar.tsx +414 -0
  62. package/Sidebar/index.ts +28 -0
  63. package/Skeleton/Skeleton.stories.tsx +117 -0
  64. package/Skeleton/Skeleton.tsx +16 -0
  65. package/Slider/Slider.stories.tsx +216 -0
  66. package/Slider/Slider.tsx +29 -0
  67. package/Spinner/Spinner.stories.tsx +210 -0
  68. package/Spinner/Spinner.tsx +78 -0
  69. package/Switch/Switch.stories.tsx +146 -0
  70. package/Switch/Switch.tsx +59 -0
  71. package/Table/Table.stories.tsx +510 -0
  72. package/Table/Table.tsx +114 -0
  73. package/Tabs/Tabs.stories.tsx +197 -0
  74. package/Tabs/Tabs.tsx +74 -0
  75. package/Textarea/Textarea.stories.tsx +187 -0
  76. package/Textarea/Textarea.tsx +73 -0
  77. package/Toast/Toast.stories.tsx +285 -0
  78. package/Toast/Toast.tsx +59 -0
  79. package/Tooltip/Tooltip.stories.tsx +463 -0
  80. package/Tooltip/Tooltip.tsx +96 -0
  81. package/Typography/Typography.stories.tsx +488 -0
  82. package/Typography/Typography.tsx +113 -0
  83. package/helpers.ts +5 -0
  84. package/{icons.js → icons.ts} +1 -1
  85. package/index.ts +217 -0
  86. package/lib/typography-types.ts +237 -0
  87. package/lib/utils.ts +15 -0
  88. package/package.json +1 -1
  89. package/tsconfig.json +22 -0
  90. package/Alert/Alert.d.ts +0 -13
  91. package/Alert/Alert.js +0 -25
  92. package/AlertDialog/AlertDialog.d.ts +0 -43
  93. package/AlertDialog/AlertDialog.js +0 -71
  94. package/Avatar/Avatar.d.ts +0 -14
  95. package/Avatar/Avatar.js +0 -25
  96. package/Badge/Badge.d.ts +0 -11
  97. package/Badge/Badge.js +0 -23
  98. package/Breadcrumb/Breadcrumb.d.ts +0 -19
  99. package/Breadcrumb/Breadcrumb.js +0 -23
  100. package/Button/Button.d.ts +0 -23
  101. package/Button/Button.js +0 -52
  102. package/Calendar/Calendar.d.ts +0 -20
  103. package/Calendar/Calendar.js +0 -78
  104. package/Card/Card.d.ts +0 -16
  105. package/Card/Card.js +0 -28
  106. package/Carousel/Carousel.d.ts +0 -37
  107. package/Carousel/Carousel.js +0 -132
  108. package/ChatBubble/ChatBubble.d.ts +0 -33
  109. package/ChatBubble/ChatBubble.js +0 -107
  110. package/Checkbox/Checkbox.d.ts +0 -12
  111. package/Checkbox/Checkbox.js +0 -20
  112. package/DataTable/DataTable.d.ts +0 -35
  113. package/DataTable/DataTable.js +0 -51
  114. package/Drawer/Drawer.d.ts +0 -33
  115. package/Drawer/Drawer.js +0 -55
  116. package/DropdownMenu/DropdownMenu.d.ts +0 -27
  117. package/DropdownMenu/DropdownMenu.js +0 -35
  118. package/ErrorMessage/ErrorMessage.d.ts +0 -27
  119. package/ErrorMessage/ErrorMessage.js +0 -14
  120. package/Flex/Flex.d.ts +0 -31
  121. package/Flex/Flex.js +0 -64
  122. package/IconButton/IconButton.d.ts +0 -23
  123. package/IconButton/IconButton.js +0 -48
  124. package/Input/Input.d.ts +0 -27
  125. package/Input/Input.js +0 -42
  126. package/InputOTP/InputOTP.d.ts +0 -20
  127. package/InputOTP/InputOTP.js +0 -44
  128. package/Label/Label.d.ts +0 -13
  129. package/Label/Label.js +0 -19
  130. package/Loader/Loader.d.ts +0 -21
  131. package/Loader/Loader.js +0 -30
  132. package/Menubar/Menubar.d.ts +0 -26
  133. package/Menubar/Menubar.js +0 -54
  134. package/Menubar/index.d.ts +0 -1
  135. package/Menubar/index.js +0 -1
  136. package/Pagination/Pagination.d.ts +0 -35
  137. package/Pagination/Pagination.js +0 -37
  138. package/Popover/Popover.d.ts +0 -7
  139. package/Popover/Popover.js +0 -10
  140. package/Progress/Progress.d.ts +0 -17
  141. package/Progress/Progress.js +0 -33
  142. package/RadioGroup/RadioGroup.d.ts +0 -13
  143. package/RadioGroup/RadioGroup.js +0 -26
  144. package/ScrollArea/ScrollArea.d.ts +0 -5
  145. package/ScrollArea/ScrollArea.js +0 -11
  146. package/Select/Select.d.ts +0 -29
  147. package/Select/Select.js +0 -50
  148. package/Separator/Separator.d.ts +0 -4
  149. package/Separator/Separator.js +0 -7
  150. package/Sidebar/Sidebar.d.ts +0 -48
  151. package/Sidebar/Sidebar.js +0 -116
  152. package/Sidebar/index.d.ts +0 -2
  153. package/Sidebar/index.js +0 -1
  154. package/Skeleton/Skeleton.d.ts +0 -4
  155. package/Skeleton/Skeleton.js +0 -7
  156. package/Slider/Slider.d.ts +0 -6
  157. package/Slider/Slider.js +0 -7
  158. package/Spinner/Spinner.d.ts +0 -19
  159. package/Spinner/Spinner.js +0 -31
  160. package/Switch/Switch.d.ts +0 -12
  161. package/Switch/Switch.js +0 -30
  162. package/Table/Table.d.ts +0 -10
  163. package/Table/Table.js +0 -20
  164. package/Tabs/Tabs.d.ts +0 -15
  165. package/Tabs/Tabs.js +0 -24
  166. package/Textarea/Textarea.d.ts +0 -19
  167. package/Textarea/Textarea.js +0 -31
  168. package/Toast/Toast.d.ts +0 -12
  169. package/Toast/Toast.js +0 -25
  170. package/Tooltip/Tooltip.d.ts +0 -17
  171. package/Tooltip/Tooltip.js +0 -29
  172. package/Typography/Typography.d.ts +0 -20
  173. package/Typography/Typography.js +0 -71
  174. package/helpers.d.ts +0 -4
  175. package/helpers.js +0 -5
  176. package/icons.d.ts +0 -1
  177. package/index.d.ts +0 -42
  178. package/index.js +0 -45
  179. package/lib/typography-types.d.ts +0 -4
  180. package/lib/typography-types.js +0 -118
  181. package/lib/utils.d.ts +0 -3
  182. package/lib/utils.js +0 -14
@@ -0,0 +1,59 @@
1
+ import * as React from "react"
2
+ import * as SwitchPrimitive from "@radix-ui/react-switch"
3
+ import { cva } from "class-variance-authority"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ type SwitchSize = "small" | "regular"
8
+
9
+ const switchVariants = cva(
10
+ "peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-accent-600 data-[state=unchecked]:bg-grey-200",
11
+ {
12
+ variants: {
13
+ size: {
14
+ small: "h-5 w-9",
15
+ regular: "h-6 w-11",
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ size: "regular",
20
+ },
21
+ }
22
+ )
23
+
24
+ const switchThumbVariants = cva(
25
+ "pointer-events-none block rounded-full bg-white shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0",
26
+ {
27
+ variants: {
28
+ size: {
29
+ small: "size-4 data-[state=checked]:translate-x-4",
30
+ regular: "size-5 data-[state=checked]:translate-x-5",
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ size: "regular",
35
+ },
36
+ }
37
+ )
38
+
39
+ export interface SwitchProps
40
+ extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> {
41
+ size?: SwitchSize
42
+ }
43
+
44
+ const Switch = React.forwardRef<
45
+ React.ElementRef<typeof SwitchPrimitive.Root>,
46
+ SwitchProps
47
+ >(({ className, size, ...props }, ref) => (
48
+ <SwitchPrimitive.Root
49
+ className={cn(switchVariants({ size }), className)}
50
+ {...props}
51
+ ref={ref}
52
+ >
53
+ <SwitchPrimitive.Thumb className={cn(switchThumbVariants({ size }))} />
54
+ </SwitchPrimitive.Root>
55
+ ))
56
+ Switch.displayName = SwitchPrimitive.Root.displayName
57
+
58
+ export { Switch, switchVariants }
59
+ export type { SwitchSize }
@@ -0,0 +1,510 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { Checkbox } from "../Checkbox/Checkbox"
3
+ import { Flex } from "../Flex/Flex"
4
+ import { Typography } from "../Typography/Typography"
5
+ import {
6
+ Table,
7
+ TableBody,
8
+ TableCaption,
9
+ TableCell,
10
+ TableFooter,
11
+ TableHead,
12
+ TableHeader,
13
+ TableRow,
14
+ } from "./Table"
15
+
16
+ const meta: Meta<typeof Table> = {
17
+ title: "Components/Table",
18
+ component: Table,
19
+ parameters: {
20
+ layout: "padded",
21
+ },
22
+ tags: ["autodocs"],
23
+ }
24
+
25
+ export default meta
26
+ type Story = StoryObj<typeof Table>
27
+
28
+ // Sample data for stories
29
+ const invoices = [
30
+ { invoice: "INV001", status: "Paid", method: "Credit Card", amount: "$250.00" },
31
+ { invoice: "INV002", status: "Pending", method: "PayPal", amount: "$150.00" },
32
+ { invoice: "INV003", status: "Unpaid", method: "Bank Transfer", amount: "$350.00" },
33
+ { invoice: "INV004", status: "Paid", method: "Credit Card", amount: "$450.00" },
34
+ { invoice: "INV005", status: "Paid", method: "PayPal", amount: "$550.00" },
35
+ { invoice: "INV006", status: "Pending", method: "Bank Transfer", amount: "$200.00" },
36
+ { invoice: "INV007", status: "Unpaid", method: "Credit Card", amount: "$300.00" },
37
+ ]
38
+
39
+ const users = [
40
+ { id: 1, name: "John Doe", email: "john@example.com", role: "Admin", status: "Active" },
41
+ { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Editor", status: "Active" },
42
+ { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "Viewer", status: "Inactive" },
43
+ { id: 4, name: "Alice Brown", email: "alice@example.com", role: "Editor", status: "Active" },
44
+ { id: 5, name: "Charlie Wilson", email: "charlie@example.com", role: "Viewer", status: "Pending" },
45
+ ]
46
+
47
+ export const Default: Story = {
48
+ render: () => (
49
+ <Table>
50
+ <TableHeader>
51
+ <TableRow>
52
+ <TableHead className="w-[100px]">Invoice</TableHead>
53
+ <TableHead>Status</TableHead>
54
+ <TableHead>Method</TableHead>
55
+ <TableHead className="text-right">Amount</TableHead>
56
+ </TableRow>
57
+ </TableHeader>
58
+ <TableBody>
59
+ {invoices.map((invoice) => (
60
+ <TableRow key={invoice.invoice}>
61
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
62
+ <TableCell>{invoice.status}</TableCell>
63
+ <TableCell>{invoice.method}</TableCell>
64
+ <TableCell className="text-right">{invoice.amount}</TableCell>
65
+ </TableRow>
66
+ ))}
67
+ </TableBody>
68
+ </Table>
69
+ ),
70
+ }
71
+
72
+ export const WithCaption: Story = {
73
+ render: () => (
74
+ <Table>
75
+ <TableCaption>A list of your recent invoices.</TableCaption>
76
+ <TableHeader>
77
+ <TableRow>
78
+ <TableHead className="w-[100px]">Invoice</TableHead>
79
+ <TableHead>Status</TableHead>
80
+ <TableHead>Method</TableHead>
81
+ <TableHead className="text-right">Amount</TableHead>
82
+ </TableRow>
83
+ </TableHeader>
84
+ <TableBody>
85
+ {invoices.slice(0, 5).map((invoice) => (
86
+ <TableRow key={invoice.invoice}>
87
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
88
+ <TableCell>{invoice.status}</TableCell>
89
+ <TableCell>{invoice.method}</TableCell>
90
+ <TableCell className="text-right">{invoice.amount}</TableCell>
91
+ </TableRow>
92
+ ))}
93
+ </TableBody>
94
+ </Table>
95
+ ),
96
+ }
97
+
98
+ export const WithFooter: Story = {
99
+ render: () => (
100
+ <Table>
101
+ <TableHeader>
102
+ <TableRow>
103
+ <TableHead className="w-[100px]">Invoice</TableHead>
104
+ <TableHead>Status</TableHead>
105
+ <TableHead>Method</TableHead>
106
+ <TableHead className="text-right">Amount</TableHead>
107
+ </TableRow>
108
+ </TableHeader>
109
+ <TableBody>
110
+ {invoices.map((invoice) => (
111
+ <TableRow key={invoice.invoice}>
112
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
113
+ <TableCell>{invoice.status}</TableCell>
114
+ <TableCell>{invoice.method}</TableCell>
115
+ <TableCell className="text-right">{invoice.amount}</TableCell>
116
+ </TableRow>
117
+ ))}
118
+ </TableBody>
119
+ <TableFooter>
120
+ <TableRow>
121
+ <TableCell colSpan={3}>Total</TableCell>
122
+ <TableCell className="text-right">$2,250.00</TableCell>
123
+ </TableRow>
124
+ </TableFooter>
125
+ </Table>
126
+ ),
127
+ }
128
+
129
+ export const Striped: Story = {
130
+ render: () => (
131
+ <Table>
132
+ <TableHeader>
133
+ <TableRow>
134
+ <TableHead>Name</TableHead>
135
+ <TableHead>Email</TableHead>
136
+ <TableHead>Role</TableHead>
137
+ <TableHead>Status</TableHead>
138
+ </TableRow>
139
+ </TableHeader>
140
+ <TableBody>
141
+ {users.map((user, index) => (
142
+ <TableRow
143
+ key={user.id}
144
+ className={index % 2 === 0 ? "bg-grey-50" : ""}
145
+ >
146
+ <TableCell className="font-medium">{user.name}</TableCell>
147
+ <TableCell>{user.email}</TableCell>
148
+ <TableCell>{user.role}</TableCell>
149
+ <TableCell>{user.status}</TableCell>
150
+ </TableRow>
151
+ ))}
152
+ </TableBody>
153
+ </Table>
154
+ ),
155
+ }
156
+
157
+ export const Compact: Story = {
158
+ render: () => (
159
+ <Table>
160
+ <TableHeader>
161
+ <TableRow>
162
+ <TableHead className="py-2 px-2">Name</TableHead>
163
+ <TableHead className="py-2 px-2">Email</TableHead>
164
+ <TableHead className="py-2 px-2">Role</TableHead>
165
+ <TableHead className="py-2 px-2">Status</TableHead>
166
+ </TableRow>
167
+ </TableHeader>
168
+ <TableBody>
169
+ {users.map((user) => (
170
+ <TableRow key={user.id}>
171
+ <TableCell className="py-1.5 px-2 font-medium">{user.name}</TableCell>
172
+ <TableCell className="py-1.5 px-2">{user.email}</TableCell>
173
+ <TableCell className="py-1.5 px-2">{user.role}</TableCell>
174
+ <TableCell className="py-1.5 px-2">{user.status}</TableCell>
175
+ </TableRow>
176
+ ))}
177
+ </TableBody>
178
+ </Table>
179
+ ),
180
+ }
181
+
182
+ export const WithCheckboxes: Story = {
183
+ render: () => (
184
+ <Table>
185
+ <TableHeader>
186
+ <TableRow>
187
+ <TableHead className="w-12">
188
+ <Checkbox />
189
+ </TableHead>
190
+ <TableHead>Name</TableHead>
191
+ <TableHead>Email</TableHead>
192
+ <TableHead>Role</TableHead>
193
+ <TableHead>Status</TableHead>
194
+ </TableRow>
195
+ </TableHeader>
196
+ <TableBody>
197
+ {users.map((user) => (
198
+ <TableRow key={user.id}>
199
+ <TableCell>
200
+ <Checkbox />
201
+ </TableCell>
202
+ <TableCell className="font-medium">{user.name}</TableCell>
203
+ <TableCell>{user.email}</TableCell>
204
+ <TableCell>{user.role}</TableCell>
205
+ <TableCell>{user.status}</TableCell>
206
+ </TableRow>
207
+ ))}
208
+ </TableBody>
209
+ </Table>
210
+ ),
211
+ }
212
+
213
+ export const SelectedRows: Story = {
214
+ render: () => (
215
+ <Table>
216
+ <TableHeader>
217
+ <TableRow>
218
+ <TableHead className="w-12">
219
+ <Checkbox />
220
+ </TableHead>
221
+ <TableHead>Name</TableHead>
222
+ <TableHead>Email</TableHead>
223
+ <TableHead>Role</TableHead>
224
+ </TableRow>
225
+ </TableHeader>
226
+ <TableBody>
227
+ {users.map((user, index) => (
228
+ <TableRow
229
+ key={user.id}
230
+ data-state={index === 1 || index === 3 ? "selected" : undefined}
231
+ >
232
+ <TableCell>
233
+ <Checkbox checked={index === 1 || index === 3} />
234
+ </TableCell>
235
+ <TableCell className="font-medium">{user.name}</TableCell>
236
+ <TableCell>{user.email}</TableCell>
237
+ <TableCell>{user.role}</TableCell>
238
+ </TableRow>
239
+ ))}
240
+ </TableBody>
241
+ </Table>
242
+ ),
243
+ }
244
+
245
+ export const EmptyState: Story = {
246
+ render: () => (
247
+ <Table>
248
+ <TableHeader>
249
+ <TableRow>
250
+ <TableHead>Invoice</TableHead>
251
+ <TableHead>Status</TableHead>
252
+ <TableHead>Method</TableHead>
253
+ <TableHead className="text-right">Amount</TableHead>
254
+ </TableRow>
255
+ </TableHeader>
256
+ <TableBody>
257
+ <TableRow>
258
+ <TableCell colSpan={4} className="h-24 text-center text-grey-500">
259
+ No invoices found.
260
+ </TableCell>
261
+ </TableRow>
262
+ </TableBody>
263
+ </Table>
264
+ ),
265
+ }
266
+
267
+ export const LongContent: Story = {
268
+ render: () => (
269
+ <Table>
270
+ <TableHeader>
271
+ <TableRow>
272
+ <TableHead className="w-[80px]">ID</TableHead>
273
+ <TableHead className="w-[200px]">Title</TableHead>
274
+ <TableHead>Description</TableHead>
275
+ <TableHead className="w-[100px]">Status</TableHead>
276
+ </TableRow>
277
+ </TableHeader>
278
+ <TableBody>
279
+ <TableRow>
280
+ <TableCell className="font-medium">1</TableCell>
281
+ <TableCell className="truncate max-w-[200px]">
282
+ This is a very long title that should be truncated
283
+ </TableCell>
284
+ <TableCell className="truncate max-w-[300px]">
285
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
286
+ </TableCell>
287
+ <TableCell>Active</TableCell>
288
+ </TableRow>
289
+ <TableRow>
290
+ <TableCell className="font-medium">2</TableCell>
291
+ <TableCell className="truncate max-w-[200px]">
292
+ Another very long title example here
293
+ </TableCell>
294
+ <TableCell className="truncate max-w-[300px]">
295
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
296
+ </TableCell>
297
+ <TableCell>Pending</TableCell>
298
+ </TableRow>
299
+ <TableRow>
300
+ <TableCell className="font-medium">3</TableCell>
301
+ <TableCell>Short title</TableCell>
302
+ <TableCell>Short description</TableCell>
303
+ <TableCell>Draft</TableCell>
304
+ </TableRow>
305
+ </TableBody>
306
+ </Table>
307
+ ),
308
+ }
309
+
310
+ export const Bordered: Story = {
311
+ render: () => (
312
+ <div className="border border-grey-200 rounded-lg overflow-hidden">
313
+ <Table>
314
+ <TableHeader>
315
+ <TableRow className="bg-grey-50">
316
+ <TableHead>Invoice</TableHead>
317
+ <TableHead>Status</TableHead>
318
+ <TableHead>Method</TableHead>
319
+ <TableHead className="text-right">Amount</TableHead>
320
+ </TableRow>
321
+ </TableHeader>
322
+ <TableBody>
323
+ {invoices.slice(0, 5).map((invoice) => (
324
+ <TableRow key={invoice.invoice}>
325
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
326
+ <TableCell>{invoice.status}</TableCell>
327
+ <TableCell>{invoice.method}</TableCell>
328
+ <TableCell className="text-right">{invoice.amount}</TableCell>
329
+ </TableRow>
330
+ ))}
331
+ </TableBody>
332
+ </Table>
333
+ </div>
334
+ ),
335
+ }
336
+
337
+ export const Showcase: Story = {
338
+ parameters: {
339
+ layout: "fullscreen",
340
+ },
341
+ render: () => (
342
+ <Flex style={{ padding: "32px", backgroundColor: "#ffffff", minHeight: "100vh" }}>
343
+ <Flex style={{ borderBottom: "1px solid #e5e7eb", paddingBottom: "24px", marginBottom: "32px" }}>
344
+ <Typography variant="h3" color="main-950">Table</Typography>
345
+ <Typography variant="body2" color="main-500" style={{ marginTop: "8px" }}>
346
+ A responsive table component with semantic HTML structure.
347
+ </Typography>
348
+ </Flex>
349
+
350
+ <Flex gap={12}>
351
+ {/* Basic Table */}
352
+ <Flex gap={4}>
353
+ <Typography variant="subtitle1" color="main-700">Basic Table</Typography>
354
+ <Table>
355
+ <TableHeader>
356
+ <TableRow>
357
+ <TableHead className="w-[100px]">Invoice</TableHead>
358
+ <TableHead>Status</TableHead>
359
+ <TableHead>Method</TableHead>
360
+ <TableHead className="text-right">Amount</TableHead>
361
+ </TableRow>
362
+ </TableHeader>
363
+ <TableBody>
364
+ {invoices.slice(0, 3).map((invoice) => (
365
+ <TableRow key={invoice.invoice}>
366
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
367
+ <TableCell>{invoice.status}</TableCell>
368
+ <TableCell>{invoice.method}</TableCell>
369
+ <TableCell className="text-right">{invoice.amount}</TableCell>
370
+ </TableRow>
371
+ ))}
372
+ </TableBody>
373
+ </Table>
374
+ </Flex>
375
+
376
+ {/* With Footer */}
377
+ <Flex gap={4}>
378
+ <Typography variant="subtitle1" color="main-700">With Footer</Typography>
379
+ <Table>
380
+ <TableHeader>
381
+ <TableRow>
382
+ <TableHead>Invoice</TableHead>
383
+ <TableHead>Status</TableHead>
384
+ <TableHead className="text-right">Amount</TableHead>
385
+ </TableRow>
386
+ </TableHeader>
387
+ <TableBody>
388
+ {invoices.slice(0, 3).map((invoice) => (
389
+ <TableRow key={invoice.invoice}>
390
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
391
+ <TableCell>{invoice.status}</TableCell>
392
+ <TableCell className="text-right">{invoice.amount}</TableCell>
393
+ </TableRow>
394
+ ))}
395
+ </TableBody>
396
+ <TableFooter>
397
+ <TableRow>
398
+ <TableCell colSpan={2}>Total</TableCell>
399
+ <TableCell className="text-right">$750.00</TableCell>
400
+ </TableRow>
401
+ </TableFooter>
402
+ </Table>
403
+ </Flex>
404
+
405
+ {/* With Caption */}
406
+ <Flex gap={4}>
407
+ <Typography variant="subtitle1" color="main-700">With Caption</Typography>
408
+ <Table>
409
+ <TableCaption>A list of your recent invoices.</TableCaption>
410
+ <TableHeader>
411
+ <TableRow>
412
+ <TableHead>Invoice</TableHead>
413
+ <TableHead>Status</TableHead>
414
+ <TableHead className="text-right">Amount</TableHead>
415
+ </TableRow>
416
+ </TableHeader>
417
+ <TableBody>
418
+ {invoices.slice(0, 3).map((invoice) => (
419
+ <TableRow key={invoice.invoice}>
420
+ <TableCell className="font-medium">{invoice.invoice}</TableCell>
421
+ <TableCell>{invoice.status}</TableCell>
422
+ <TableCell className="text-right">{invoice.amount}</TableCell>
423
+ </TableRow>
424
+ ))}
425
+ </TableBody>
426
+ </Table>
427
+ </Flex>
428
+
429
+ {/* With Selection */}
430
+ <Flex gap={4}>
431
+ <Typography variant="subtitle1" color="main-700">With Selection</Typography>
432
+ <Table>
433
+ <TableHeader>
434
+ <TableRow>
435
+ <TableHead className="w-12">
436
+ <Checkbox />
437
+ </TableHead>
438
+ <TableHead>Name</TableHead>
439
+ <TableHead>Email</TableHead>
440
+ <TableHead>Role</TableHead>
441
+ </TableRow>
442
+ </TableHeader>
443
+ <TableBody>
444
+ {users.slice(0, 3).map((user, index) => (
445
+ <TableRow
446
+ key={user.id}
447
+ data-state={index === 1 ? "selected" : undefined}
448
+ >
449
+ <TableCell>
450
+ <Checkbox checked={index === 1} />
451
+ </TableCell>
452
+ <TableCell className="font-medium">{user.name}</TableCell>
453
+ <TableCell>{user.email}</TableCell>
454
+ <TableCell>{user.role}</TableCell>
455
+ </TableRow>
456
+ ))}
457
+ </TableBody>
458
+ </Table>
459
+ </Flex>
460
+
461
+ {/* Striped */}
462
+ <Flex gap={4}>
463
+ <Typography variant="subtitle1" color="main-700">Striped Rows</Typography>
464
+ <Table>
465
+ <TableHeader>
466
+ <TableRow>
467
+ <TableHead>Name</TableHead>
468
+ <TableHead>Email</TableHead>
469
+ <TableHead>Status</TableHead>
470
+ </TableRow>
471
+ </TableHeader>
472
+ <TableBody>
473
+ {users.slice(0, 4).map((user, index) => (
474
+ <TableRow
475
+ key={user.id}
476
+ className={index % 2 === 0 ? "bg-grey-50" : ""}
477
+ >
478
+ <TableCell className="font-medium">{user.name}</TableCell>
479
+ <TableCell>{user.email}</TableCell>
480
+ <TableCell>{user.status}</TableCell>
481
+ </TableRow>
482
+ ))}
483
+ </TableBody>
484
+ </Table>
485
+ </Flex>
486
+
487
+ {/* Empty State */}
488
+ <Flex gap={4}>
489
+ <Typography variant="subtitle1" color="main-700">Empty State</Typography>
490
+ <Table>
491
+ <TableHeader>
492
+ <TableRow>
493
+ <TableHead>Invoice</TableHead>
494
+ <TableHead>Status</TableHead>
495
+ <TableHead className="text-right">Amount</TableHead>
496
+ </TableRow>
497
+ </TableHeader>
498
+ <TableBody>
499
+ <TableRow>
500
+ <TableCell colSpan={3} className="h-24 text-center text-grey-500">
501
+ No results found.
502
+ </TableCell>
503
+ </TableRow>
504
+ </TableBody>
505
+ </Table>
506
+ </Flex>
507
+ </Flex>
508
+ </Flex>
509
+ ),
510
+ }
@@ -0,0 +1,114 @@
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ const Table = React.forwardRef<
5
+ HTMLTableElement,
6
+ React.HTMLAttributes<HTMLTableElement>
7
+ >(({ className, ...props }, ref) => (
8
+ <table
9
+ ref={ref}
10
+ className={cn("w-full caption-bottom text-sm", className)}
11
+ {...props}
12
+ />
13
+ ))
14
+ Table.displayName = "Table"
15
+
16
+ const TableHeader = React.forwardRef<
17
+ HTMLTableSectionElement,
18
+ React.HTMLAttributes<HTMLTableSectionElement>
19
+ >(({ className, ...props }, ref) => (
20
+ <thead ref={ref} className={cn("bg-background-neutral-200 [&_tr]:border-b [&_tr]:hover:bg-background-neutral-200", className)} {...props} />
21
+ ))
22
+ TableHeader.displayName = "TableHeader"
23
+
24
+ const TableBody = React.forwardRef<
25
+ HTMLTableSectionElement,
26
+ React.HTMLAttributes<HTMLTableSectionElement>
27
+ >(({ className, ...props }, ref) => (
28
+ <tbody
29
+ ref={ref}
30
+ className={cn("[&_tr:last-child]:border-0", className)}
31
+ {...props}
32
+ />
33
+ ))
34
+ TableBody.displayName = "TableBody"
35
+
36
+ const TableFooter = React.forwardRef<
37
+ HTMLTableSectionElement,
38
+ React.HTMLAttributes<HTMLTableSectionElement>
39
+ >(({ className, ...props }, ref) => (
40
+ <tfoot
41
+ ref={ref}
42
+ className={cn(
43
+ "border-t bg-background-neutral-200 font-medium text-main-900 [&>tr]:last:border-b-0",
44
+ className,
45
+ )}
46
+ {...props}
47
+ />
48
+ ))
49
+ TableFooter.displayName = "TableFooter"
50
+
51
+ const TableRow = React.forwardRef<
52
+ HTMLTableRowElement,
53
+ React.HTMLAttributes<HTMLTableRowElement>
54
+ >(({ className, ...props }, ref) => (
55
+ <tr
56
+ ref={ref}
57
+ className={cn(
58
+ "border-b border-grey-200 transition-colors hover:bg-grey-50 data-[state=selected]:bg-grey-100",
59
+ className,
60
+ )}
61
+ {...props}
62
+ />
63
+ ))
64
+ TableRow.displayName = "TableRow"
65
+
66
+ const TableHead = React.forwardRef<
67
+ HTMLTableCellElement,
68
+ React.ThHTMLAttributes<HTMLTableCellElement>
69
+ >(({ className, ...props }, ref) => (
70
+ <th
71
+ ref={ref}
72
+ className={cn(
73
+ "h-10 px-3 text-left align-middle font-normal text-main-900 [&:has([role=checkbox])]:pr-0",
74
+ className,
75
+ )}
76
+ {...props}
77
+ />
78
+ ))
79
+ TableHead.displayName = "TableHead"
80
+
81
+ const TableCell = React.forwardRef<
82
+ HTMLTableCellElement,
83
+ React.TdHTMLAttributes<HTMLTableCellElement>
84
+ >(({ className, ...props }, ref) => (
85
+ <td
86
+ ref={ref}
87
+ className={cn("p-3 align-middle text-main-700 [&:has([role=checkbox])]:pr-0", className)}
88
+ {...props}
89
+ />
90
+ ))
91
+ TableCell.displayName = "TableCell"
92
+
93
+ const TableCaption = React.forwardRef<
94
+ HTMLTableCaptionElement,
95
+ React.HTMLAttributes<HTMLTableCaptionElement>
96
+ >(({ className, ...props }, ref) => (
97
+ <caption
98
+ ref={ref}
99
+ className={cn("mt-4 text-sm text-main-700", className)}
100
+ {...props}
101
+ />
102
+ ))
103
+ TableCaption.displayName = "TableCaption"
104
+
105
+ export {
106
+ Table,
107
+ TableHeader,
108
+ TableBody,
109
+ TableFooter,
110
+ TableHead,
111
+ TableRow,
112
+ TableCell,
113
+ TableCaption,
114
+ }