@gsk_poc/untitled-ui-base 0.1.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/LICENSE +21 -0
- package/README.md +44 -0
- package/components/application/app-navigation/base-components/featured-cards.demo.tsx +86 -0
- package/components/application/app-navigation/base-components/featured-cards.story.tsx +49 -0
- package/components/application/app-navigation/header-navigation.demo.tsx +59 -0
- package/components/application/app-navigation/header-navigation.story.tsx +23 -0
- package/components/application/app-navigation/sidebar-navigation.demo.tsx +409 -0
- package/components/application/app-navigation/sidebar-navigation.story.tsx +47 -0
- package/components/application/carousel/carousel.demo.tsx +107 -0
- package/components/application/carousel/carousel.story.tsx +21 -0
- package/components/application/charts/activity-gauges.demo.tsx +251 -0
- package/components/application/charts/activity-gauges.story.tsx +27 -0
- package/components/application/charts/bar-charts.demo.tsx +506 -0
- package/components/application/charts/bar-charts.story.tsx +36 -0
- package/components/application/charts/line-charts.demo.tsx +604 -0
- package/components/application/charts/line-charts.story.tsx +43 -0
- package/components/application/charts/pie-charts.demo.tsx +193 -0
- package/components/application/charts/pie-charts.story.tsx +30 -0
- package/components/application/charts/progress-circles.demo.tsx +110 -0
- package/components/application/charts/progress-circles.story.tsx +33 -0
- package/components/application/charts/radar-charts.demo.tsx +203 -0
- package/components/application/charts/radar-charts.story.tsx +18 -0
- package/components/application/date-picker/date-picker.demo.tsx +217 -0
- package/components/application/date-picker/date-picker.story.tsx +44 -0
- package/components/application/file-upload/file-upload.demo.tsx +292 -0
- package/components/application/file-upload/file-upload.story.tsx +70 -0
- package/components/application/loading-indicator/loading-indicator.demo.tsx +73 -0
- package/components/application/loading-indicator/loading-indicator.story.tsx +22 -0
- package/components/application/pagination/pagination.demo.tsx +104 -0
- package/components/application/pagination/pagination.story.tsx +54 -0
- package/components/application/table/table.demo.tsx +1038 -0
- package/components/application/table/table.story.tsx +119 -0
- package/components/application/tabs/tabs.demo.tsx +322 -0
- package/components/application/tabs/tabs.story.tsx +43 -0
- package/components/base/avatar/avatar.demo.tsx +865 -0
- package/components/base/avatar/avatar.story.tsx +27 -0
- package/components/base/badges/badge-groups.demo.tsx +357 -0
- package/components/base/badges/badge-groups.story.tsx +25 -0
- package/components/base/badges/badges.demo.tsx +497 -0
- package/components/base/badges/badges.story.tsx +83 -0
- package/components/base/button-group/button-group.demo.tsx +131 -0
- package/components/base/button-group/button-group.story.tsx +16 -0
- package/components/base/buttons/app-store-buttons.demo.tsx +129 -0
- package/components/base/buttons/app-store-buttons.story.tsx +13 -0
- package/components/base/buttons/buttons.demo.tsx +1022 -0
- package/components/base/buttons/buttons.story.tsx +42 -0
- package/components/base/buttons/social-buttons.demo.tsx +432 -0
- package/components/base/buttons/social-buttons.story.tsx +20 -0
- package/components/base/checkbox/checkbox.demo.tsx +62 -0
- package/components/base/checkbox/checkbox.story.tsx +18 -0
- package/components/base/dropdown/dropdown.demo.tsx +137 -0
- package/components/base/dropdown/dropdown.story.tsx +22 -0
- package/components/base/input/inputs.demo.tsx +758 -0
- package/components/base/input/inputs.story.tsx +52 -0
- package/components/base/pin-input/pin-input.demo.tsx +126 -0
- package/components/base/pin-input/pin-input.story.tsx +22 -0
- package/components/base/progress-indicators/progress-indicators.demo.tsx +54 -0
- package/components/base/progress-indicators/progress-indicators.story.tsx +57 -0
- package/components/base/radio-buttons/radio-buttons.demo.tsx +77 -0
- package/components/base/radio-buttons/radio-buttons.story.tsx +19 -0
- package/components/base/select/select.demo.tsx +936 -0
- package/components/base/select/select.story.tsx +43 -0
- package/components/base/slider/slider.demo.tsx +19 -0
- package/components/base/slider/slider.story.tsx +26 -0
- package/components/base/tags/tags.demo.tsx +341 -0
- package/components/base/tags/tags.story.tsx +28 -0
- package/components/base/textarea/textarea.demo.tsx +25 -0
- package/components/base/textarea/textarea.story.tsx +15 -0
- package/components/base/toggle/toggle.demo.tsx +76 -0
- package/components/base/toggle/toggle.story.tsx +23 -0
- package/components/base/tooltip/tooltip.demo.tsx +125 -0
- package/components/base/tooltip/tooltip.story.tsx +21 -0
- package/components/foundations/featured-icon/featured-icon.demo.tsx +160 -0
- package/components/foundations/featured-icon/featured-icon.story.tsx +25 -0
- package/components/shared-assets/credit-card/credit-card.demo.tsx +106 -0
- package/components/shared-assets/credit-card/credit-card.story.tsx +41 -0
- package/dist/index.d.mts +1417 -0
- package/dist/index.d.ts +1417 -0
- package/dist/index.js +10435 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +10345 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +126 -0
- package/styles/globals.css +65 -0
- package/styles/theme.css +430 -0
- package/styles/tokens-mapped.css +233 -0
- package/styles/tokens.css +807 -0
- package/styles/typography.css +430 -0
- package/tokens/design-tokens.dtcg.json +3515 -0
|
@@ -0,0 +1,1038 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { FileIcon } from "@untitledui/file-icons";
|
|
5
|
+
import { AlertCircle, Check, Edit01, FilterLines, Plus, ReverseLeft, SearchLg, Trash01, UploadCloud02, X } from "@untitledui/icons";
|
|
6
|
+
import type { SortDescriptor } from "react-aria-components";
|
|
7
|
+
import { EmptyState } from "@/components/application/empty-state/empty-state";
|
|
8
|
+
import { PaginationCardMinimal, PaginationPageMinimalCenter } from "@/components/application/pagination/pagination";
|
|
9
|
+
import customers from "@/components/application/table/customers.json";
|
|
10
|
+
import invoices from "@/components/application/table/invoices.json";
|
|
11
|
+
import { Table, TableCard, TableRowActionsDropdown } from "@/components/application/table/table";
|
|
12
|
+
import teamMembers from "@/components/application/table/team-members.json";
|
|
13
|
+
import uploadedFiles from "@/components/application/table/uploaded-files.json";
|
|
14
|
+
import { Avatar } from "@/components/base/avatar/avatar";
|
|
15
|
+
import type { BadgeTypes } from "@/components/base/badges/badge-types";
|
|
16
|
+
import { Badge, type BadgeColor, BadgeWithDot, BadgeWithIcon } from "@/components/base/badges/badges";
|
|
17
|
+
import { ButtonGroup, ButtonGroupItem } from "@/components/base/button-group/button-group";
|
|
18
|
+
import { Button } from "@/components/base/buttons/button";
|
|
19
|
+
import { ButtonUtility } from "@/components/base/buttons/button-utility";
|
|
20
|
+
import { Input } from "@/components/base/input/input";
|
|
21
|
+
import { ProgressBar } from "@/components/base/progress-indicators/progress-indicators";
|
|
22
|
+
|
|
23
|
+
export const Table01DividerLine = () => {
|
|
24
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
25
|
+
column: "status",
|
|
26
|
+
direction: "ascending",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const sortedItems = useMemo(() => {
|
|
30
|
+
return teamMembers.items.sort((a, b) => {
|
|
31
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
32
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
33
|
+
|
|
34
|
+
// Compare numbers or booleans
|
|
35
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
36
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Compare strings
|
|
40
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
41
|
+
let cmp = first.localeCompare(second);
|
|
42
|
+
if (sortDescriptor.direction === "descending") {
|
|
43
|
+
cmp *= -1;
|
|
44
|
+
}
|
|
45
|
+
return cmp;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return 0;
|
|
49
|
+
});
|
|
50
|
+
}, [sortDescriptor]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<TableCard.Root>
|
|
54
|
+
<TableCard.Header
|
|
55
|
+
title="Team members"
|
|
56
|
+
badge="100 users"
|
|
57
|
+
contentTrailing={
|
|
58
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
59
|
+
<TableRowActionsDropdown />
|
|
60
|
+
</div>
|
|
61
|
+
}
|
|
62
|
+
/>
|
|
63
|
+
<Table aria-label="Team members" selectionMode="multiple" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
64
|
+
<Table.Header>
|
|
65
|
+
<Table.Head id="name" label="Name" isRowHeader allowsSorting className="w-full max-w-1/4" />
|
|
66
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
67
|
+
<Table.Head id="role" label="Role" allowsSorting tooltip="This is a tooltip" />
|
|
68
|
+
<Table.Head id="email" label="Email address" allowsSorting className="md:hidden xl:table-cell" />
|
|
69
|
+
<Table.Head id="teams" label="Teams" />
|
|
70
|
+
<Table.Head id="actions" />
|
|
71
|
+
</Table.Header>
|
|
72
|
+
|
|
73
|
+
<Table.Body items={sortedItems}>
|
|
74
|
+
{(item) => (
|
|
75
|
+
<Table.Row id={item.username}>
|
|
76
|
+
<Table.Cell>
|
|
77
|
+
<div className="flex items-center gap-3">
|
|
78
|
+
<Avatar src={item.avatarUrl} alt={item.name} size="md" />
|
|
79
|
+
<div className="whitespace-nowrap">
|
|
80
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
81
|
+
<p className="text-sm text-tertiary">{item.username}</p>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</Table.Cell>
|
|
85
|
+
<Table.Cell>
|
|
86
|
+
<BadgeWithDot size="sm" color={item.status === "active" ? "success" : "gray"} type="modern">
|
|
87
|
+
{item.status === "active" ? "Active" : "Inactive"}
|
|
88
|
+
</BadgeWithDot>
|
|
89
|
+
</Table.Cell>
|
|
90
|
+
<Table.Cell className="whitespace-nowrap">{item.role}</Table.Cell>
|
|
91
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.email}</Table.Cell>
|
|
92
|
+
<Table.Cell>
|
|
93
|
+
<div className="flex gap-1">
|
|
94
|
+
{item.teams.slice(0, 3).map((team) => (
|
|
95
|
+
<Badge key={team.name} color={team.color as BadgeColor<BadgeTypes>} size="sm">
|
|
96
|
+
{team.name}
|
|
97
|
+
</Badge>
|
|
98
|
+
))}
|
|
99
|
+
|
|
100
|
+
{item.teams.length > 3 && (
|
|
101
|
+
<Badge color="gray" size="sm">
|
|
102
|
+
+{item.teams.length - 3}
|
|
103
|
+
</Badge>
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
</Table.Cell>
|
|
107
|
+
<Table.Cell className="px-4">
|
|
108
|
+
<div className="flex justify-end gap-0.5">
|
|
109
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Delete" icon={Trash01} />
|
|
110
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Edit" icon={Edit01} />
|
|
111
|
+
</div>
|
|
112
|
+
</Table.Cell>
|
|
113
|
+
</Table.Row>
|
|
114
|
+
)}
|
|
115
|
+
</Table.Body>
|
|
116
|
+
</Table>
|
|
117
|
+
|
|
118
|
+
<PaginationPageMinimalCenter page={1} total={10} className="px-4 py-3 md:px-6 md:pt-3 md:pb-4" />
|
|
119
|
+
</TableCard.Root>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const Table01AlternatingFills = () => {
|
|
124
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
125
|
+
column: "status",
|
|
126
|
+
direction: "ascending",
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const sortedItems = useMemo(() => {
|
|
130
|
+
return teamMembers.items.sort((a, b) => {
|
|
131
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
132
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
133
|
+
|
|
134
|
+
// Compare numbers or booleans
|
|
135
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
136
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Compare strings
|
|
140
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
141
|
+
let cmp = first.localeCompare(second);
|
|
142
|
+
if (sortDescriptor.direction === "descending") {
|
|
143
|
+
cmp *= -1;
|
|
144
|
+
}
|
|
145
|
+
return cmp;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return 0;
|
|
149
|
+
});
|
|
150
|
+
}, [sortDescriptor]);
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<TableCard.Root>
|
|
154
|
+
<TableCard.Header
|
|
155
|
+
title="Team members"
|
|
156
|
+
badge="100 users"
|
|
157
|
+
contentTrailing={
|
|
158
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
159
|
+
<TableRowActionsDropdown />
|
|
160
|
+
</div>
|
|
161
|
+
}
|
|
162
|
+
/>
|
|
163
|
+
<Table aria-label="Team members" selectionMode="multiple" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
164
|
+
<Table.Header className="bg-primary">
|
|
165
|
+
<Table.Head id="name" label="Name" isRowHeader allowsSorting className="w-full max-w-1/4" />
|
|
166
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
167
|
+
<Table.Head id="role" label="Role" allowsSorting tooltip="This is a tooltip" />
|
|
168
|
+
<Table.Head id="email" label="Email address" allowsSorting className="md:hidden xl:table-cell" />
|
|
169
|
+
<Table.Head id="teams" label="Teams" />
|
|
170
|
+
<Table.Head id="actions" />
|
|
171
|
+
</Table.Header>
|
|
172
|
+
<Table.Body items={sortedItems}>
|
|
173
|
+
{(item) => (
|
|
174
|
+
<Table.Row id={item.username} className="odd:bg-secondary_subtle">
|
|
175
|
+
<Table.Cell>
|
|
176
|
+
<div className="flex items-center gap-3">
|
|
177
|
+
<Avatar src={item.avatarUrl} alt={item.name} size="md" />
|
|
178
|
+
<div className="whitespace-nowrap">
|
|
179
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
180
|
+
<p className="text-sm text-tertiary">{item.username}</p>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</Table.Cell>
|
|
184
|
+
<Table.Cell>
|
|
185
|
+
<BadgeWithDot size="sm" color={item.status === "active" ? "success" : "gray"} type="modern">
|
|
186
|
+
{item.status === "active" ? "Active" : "Inactive"}
|
|
187
|
+
</BadgeWithDot>
|
|
188
|
+
</Table.Cell>
|
|
189
|
+
<Table.Cell className="whitespace-nowrap">{item.role}</Table.Cell>
|
|
190
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.email}</Table.Cell>
|
|
191
|
+
<Table.Cell>
|
|
192
|
+
<div className="flex gap-1">
|
|
193
|
+
{item.teams.slice(0, 3).map((team) => (
|
|
194
|
+
<Badge key={team.name} color={team.color as BadgeColor<BadgeTypes>} size="sm">
|
|
195
|
+
{team.name}
|
|
196
|
+
</Badge>
|
|
197
|
+
))}
|
|
198
|
+
|
|
199
|
+
{item.teams.length > 3 && (
|
|
200
|
+
<Badge color="gray" size="sm">
|
|
201
|
+
+{item.teams.length - 3}
|
|
202
|
+
</Badge>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
</Table.Cell>
|
|
206
|
+
<Table.Cell className="px-4">
|
|
207
|
+
<div className="flex justify-end gap-0.5">
|
|
208
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Delete" icon={Trash01} />
|
|
209
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Edit" icon={Edit01} />
|
|
210
|
+
</div>
|
|
211
|
+
</Table.Cell>
|
|
212
|
+
</Table.Row>
|
|
213
|
+
)}
|
|
214
|
+
</Table.Body>
|
|
215
|
+
</Table>
|
|
216
|
+
|
|
217
|
+
<PaginationPageMinimalCenter page={1} total={10} className="px-4 py-3 md:px-6 md:pt-3 md:pb-4" />
|
|
218
|
+
</TableCard.Root>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export const Table01DividerLineSm = () => {
|
|
223
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
224
|
+
column: "status",
|
|
225
|
+
direction: "ascending",
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const sortedItems = useMemo(() => {
|
|
229
|
+
return teamMembers.items.sort((a, b) => {
|
|
230
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
231
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
232
|
+
|
|
233
|
+
// Compare numbers or booleans
|
|
234
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
235
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Compare strings
|
|
239
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
240
|
+
let cmp = first.localeCompare(second);
|
|
241
|
+
if (sortDescriptor.direction === "descending") {
|
|
242
|
+
cmp *= -1;
|
|
243
|
+
}
|
|
244
|
+
return cmp;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return 0;
|
|
248
|
+
});
|
|
249
|
+
}, [sortDescriptor]);
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<TableCard.Root size="sm">
|
|
253
|
+
<TableCard.Header
|
|
254
|
+
title="Team members"
|
|
255
|
+
badge="100 users"
|
|
256
|
+
contentTrailing={
|
|
257
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
258
|
+
<TableRowActionsDropdown />
|
|
259
|
+
</div>
|
|
260
|
+
}
|
|
261
|
+
/>
|
|
262
|
+
<Table aria-label="Team members" selectionMode="multiple" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
263
|
+
<Table.Header>
|
|
264
|
+
<Table.Head id="name" label="Name" isRowHeader allowsSorting className="w-full max-w-1/4" />
|
|
265
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
266
|
+
<Table.Head id="role" label="Role" allowsSorting tooltip="This is a tooltip" />
|
|
267
|
+
<Table.Head id="email" label="Email address" allowsSorting className="md:hidden xl:table-cell" />
|
|
268
|
+
<Table.Head id="teams" label="Teams" />
|
|
269
|
+
<Table.Head id="actions" />
|
|
270
|
+
</Table.Header>
|
|
271
|
+
|
|
272
|
+
<Table.Body items={sortedItems}>
|
|
273
|
+
{(item) => (
|
|
274
|
+
<Table.Row id={item.username}>
|
|
275
|
+
<Table.Cell>
|
|
276
|
+
<div className="flex items-center gap-2">
|
|
277
|
+
<Avatar src={item.avatarUrl} alt={item.name} size="sm" />
|
|
278
|
+
<p className="text-sm font-medium whitespace-nowrap text-primary">{item.name}</p>
|
|
279
|
+
</div>
|
|
280
|
+
</Table.Cell>
|
|
281
|
+
<Table.Cell>
|
|
282
|
+
<BadgeWithDot size="sm" color={item.status === "active" ? "success" : "gray"} type="modern">
|
|
283
|
+
{item.status === "active" ? "Active" : "Inactive"}
|
|
284
|
+
</BadgeWithDot>
|
|
285
|
+
</Table.Cell>
|
|
286
|
+
<Table.Cell className="whitespace-nowrap">{item.role}</Table.Cell>
|
|
287
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.email}</Table.Cell>
|
|
288
|
+
<Table.Cell>
|
|
289
|
+
<div className="flex gap-1">
|
|
290
|
+
{item.teams.slice(0, 3).map((team) => (
|
|
291
|
+
<Badge key={team.name} color={team.color as BadgeColor<BadgeTypes>} size="sm">
|
|
292
|
+
{team.name}
|
|
293
|
+
</Badge>
|
|
294
|
+
))}
|
|
295
|
+
|
|
296
|
+
{item.teams.length > 3 && (
|
|
297
|
+
<Badge color="gray" size="sm">
|
|
298
|
+
+{item.teams.length - 3}
|
|
299
|
+
</Badge>
|
|
300
|
+
)}
|
|
301
|
+
</div>
|
|
302
|
+
</Table.Cell>
|
|
303
|
+
<Table.Cell className="px-3">
|
|
304
|
+
<div className="flex justify-end gap-0.5">
|
|
305
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Delete" icon={Trash01} />
|
|
306
|
+
<ButtonUtility size="xs" color="tertiary" tooltip="Edit" icon={Edit01} />
|
|
307
|
+
</div>
|
|
308
|
+
</Table.Cell>
|
|
309
|
+
</Table.Row>
|
|
310
|
+
)}
|
|
311
|
+
</Table.Body>
|
|
312
|
+
</Table>
|
|
313
|
+
|
|
314
|
+
<PaginationCardMinimal align="right" page={1} total={10} className="px-4 py-3 md:px-5 md:pt-3 md:pb-4" />
|
|
315
|
+
</TableCard.Root>
|
|
316
|
+
);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export const Table02DividerLine = () => {
|
|
320
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
321
|
+
column: "status",
|
|
322
|
+
direction: "ascending",
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const sortedItems = useMemo(() => {
|
|
326
|
+
return customers.items.sort((a, b) => {
|
|
327
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
328
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
329
|
+
|
|
330
|
+
// Compare numbers or booleans
|
|
331
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
332
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Compare strings
|
|
336
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
337
|
+
let cmp = first.localeCompare(second);
|
|
338
|
+
if (sortDescriptor.direction === "descending") {
|
|
339
|
+
cmp *= -1;
|
|
340
|
+
}
|
|
341
|
+
return cmp;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return 0;
|
|
345
|
+
});
|
|
346
|
+
}, [sortDescriptor]);
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<TableCard.Root>
|
|
350
|
+
<TableCard.Header
|
|
351
|
+
title="Customers"
|
|
352
|
+
description="These companies have purchased in the last 12 months."
|
|
353
|
+
contentTrailing={
|
|
354
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
355
|
+
<TableRowActionsDropdown />
|
|
356
|
+
</div>
|
|
357
|
+
}
|
|
358
|
+
/>
|
|
359
|
+
|
|
360
|
+
<Table aria-label="Team members" selectionMode="none" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
361
|
+
<Table.Header>
|
|
362
|
+
<Table.Head id="name" label="Company" isRowHeader allowsSorting />
|
|
363
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
364
|
+
<Table.Head id="aboutTitle" label="About" allowsSorting />
|
|
365
|
+
<Table.Head id="users" label="Users" className="md:hidden xl:table-cell" />
|
|
366
|
+
<Table.Head id="licenseUse" label="License use" allowsSorting className="min-w-55" />
|
|
367
|
+
<Table.Head id="actions" />
|
|
368
|
+
</Table.Header>
|
|
369
|
+
<Table.Body items={sortedItems}>
|
|
370
|
+
{(item) => (
|
|
371
|
+
<Table.Row id={item.name}>
|
|
372
|
+
<Table.Cell>
|
|
373
|
+
<div className="flex items-center gap-3">
|
|
374
|
+
<Avatar src={item.logoUrl} alt={item.name} size="md" />
|
|
375
|
+
<div className="whitespace-nowrap">
|
|
376
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
377
|
+
<p className="text-sm text-tertiary">{item.website}</p>
|
|
378
|
+
</div>
|
|
379
|
+
</div>
|
|
380
|
+
</Table.Cell>
|
|
381
|
+
<Table.Cell>
|
|
382
|
+
<BadgeWithDot size="sm" color={item.status === "Customer" ? "success" : "gray"}>
|
|
383
|
+
{item.status}
|
|
384
|
+
</BadgeWithDot>
|
|
385
|
+
</Table.Cell>
|
|
386
|
+
<Table.Cell className="whitespace-nowrap">
|
|
387
|
+
<p className="text-sm font-medium text-primary">{item.aboutTitle}</p>
|
|
388
|
+
<p className="text-sm text-tertiary">{item.aboutDescription}</p>
|
|
389
|
+
</Table.Cell>
|
|
390
|
+
<Table.Cell className="pr-0 md:hidden xl:table-cell">
|
|
391
|
+
<div className="flex -space-x-1">
|
|
392
|
+
<Avatar
|
|
393
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
394
|
+
size="xs"
|
|
395
|
+
src="https://www.untitledui.com/images/avatars/olivia-rhye?fm=webp&q=80"
|
|
396
|
+
alt="Olivia Rhye"
|
|
397
|
+
/>
|
|
398
|
+
<Avatar
|
|
399
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
400
|
+
size="xs"
|
|
401
|
+
src="https://www.untitledui.com/images/avatars/phoenix-baker?fm=webp&q=80"
|
|
402
|
+
alt="Phoenix Baker"
|
|
403
|
+
/>
|
|
404
|
+
<Avatar
|
|
405
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
406
|
+
size="xs"
|
|
407
|
+
src="https://www.untitledui.com/images/avatars/lana-steiner?fm=webp&q=80"
|
|
408
|
+
alt="Lana Steiner"
|
|
409
|
+
/>
|
|
410
|
+
<Avatar
|
|
411
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
412
|
+
size="xs"
|
|
413
|
+
src="https://www.untitledui.com/images/avatars/demi-wilkinson?fm=webp&q=80"
|
|
414
|
+
alt="Demi Wilkinson"
|
|
415
|
+
/>
|
|
416
|
+
<Avatar
|
|
417
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
418
|
+
size="xs"
|
|
419
|
+
src="https://www.untitledui.com/images/avatars/candice-wu?fm=webp&q=80"
|
|
420
|
+
alt="Candice Wu"
|
|
421
|
+
/>
|
|
422
|
+
<Avatar
|
|
423
|
+
size="xs"
|
|
424
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
425
|
+
placeholder={<span className="text-xs font-semibold text-quaternary">+5</span>}
|
|
426
|
+
/>
|
|
427
|
+
</div>
|
|
428
|
+
</Table.Cell>
|
|
429
|
+
<Table.Cell>
|
|
430
|
+
<ProgressBar labelPosition="right" value={item.licenseUse} />
|
|
431
|
+
</Table.Cell>
|
|
432
|
+
<Table.Cell className="px-4">
|
|
433
|
+
<div className="flex items-center justify-end">
|
|
434
|
+
<TableRowActionsDropdown />
|
|
435
|
+
</div>
|
|
436
|
+
</Table.Cell>
|
|
437
|
+
</Table.Row>
|
|
438
|
+
)}
|
|
439
|
+
</Table.Body>
|
|
440
|
+
</Table>
|
|
441
|
+
</TableCard.Root>
|
|
442
|
+
);
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
export const Table02AlternatingFills = () => {
|
|
446
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
447
|
+
column: "status",
|
|
448
|
+
direction: "ascending",
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
const sortedItems = useMemo(() => {
|
|
452
|
+
return customers.items.sort((a, b) => {
|
|
453
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
454
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
455
|
+
|
|
456
|
+
// Compare numbers or booleans
|
|
457
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
458
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Compare strings
|
|
462
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
463
|
+
let cmp = first.localeCompare(second);
|
|
464
|
+
if (sortDescriptor.direction === "descending") {
|
|
465
|
+
cmp *= -1;
|
|
466
|
+
}
|
|
467
|
+
return cmp;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return 0;
|
|
471
|
+
});
|
|
472
|
+
}, [sortDescriptor]);
|
|
473
|
+
|
|
474
|
+
return (
|
|
475
|
+
<TableCard.Root>
|
|
476
|
+
<TableCard.Header
|
|
477
|
+
title="Customers"
|
|
478
|
+
description="These companies have purchased in the last 12 months."
|
|
479
|
+
contentTrailing={
|
|
480
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
481
|
+
<TableRowActionsDropdown />
|
|
482
|
+
</div>
|
|
483
|
+
}
|
|
484
|
+
/>
|
|
485
|
+
<Table aria-label="Team members" selectionMode="none" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
486
|
+
<Table.Header className="bg-primary">
|
|
487
|
+
<Table.Head id="name" label="Company" isRowHeader allowsSorting />
|
|
488
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
489
|
+
<Table.Head id="aboutTitle" label="About" allowsSorting />
|
|
490
|
+
<Table.Head id="users" label="Users" className="md:hidden xl:table-cell" />
|
|
491
|
+
<Table.Head id="licenseUse" label="License use" allowsSorting className="min-w-55" />
|
|
492
|
+
<Table.Head id="actions" />
|
|
493
|
+
</Table.Header>
|
|
494
|
+
<Table.Body items={sortedItems}>
|
|
495
|
+
{(item) => (
|
|
496
|
+
<Table.Row id={item.name} className="odd:bg-secondary_subtle">
|
|
497
|
+
<Table.Cell>
|
|
498
|
+
<div className="flex items-center gap-3">
|
|
499
|
+
<Avatar src={item.logoUrl} alt={item.name} size="md" />
|
|
500
|
+
<div className="whitespace-nowrap">
|
|
501
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
502
|
+
<p className="text-sm text-tertiary">{item.website}</p>
|
|
503
|
+
</div>
|
|
504
|
+
</div>
|
|
505
|
+
</Table.Cell>
|
|
506
|
+
<Table.Cell>
|
|
507
|
+
<BadgeWithDot size="sm" color={item.status === "Customer" ? "success" : "gray"} type="modern">
|
|
508
|
+
{item.status}
|
|
509
|
+
</BadgeWithDot>
|
|
510
|
+
</Table.Cell>
|
|
511
|
+
<Table.Cell className="whitespace-nowrap">
|
|
512
|
+
<p className="text-sm font-medium text-primary">{item.aboutTitle}</p>
|
|
513
|
+
<p className="text-sm text-tertiary">{item.aboutDescription}</p>
|
|
514
|
+
</Table.Cell>
|
|
515
|
+
<Table.Cell className="pr-0 md:hidden xl:table-cell">
|
|
516
|
+
<div className="flex -space-x-1">
|
|
517
|
+
<Avatar
|
|
518
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
519
|
+
size="xs"
|
|
520
|
+
src="https://www.untitledui.com/images/avatars/olivia-rhye?fm=webp&q=80&w=100"
|
|
521
|
+
alt="Olivia Rhye"
|
|
522
|
+
/>
|
|
523
|
+
<Avatar
|
|
524
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
525
|
+
size="xs"
|
|
526
|
+
src="https://www.untitledui.com/images/avatars/phoenix-baker?fm=webp&q=80&w=100"
|
|
527
|
+
alt="Phoenix Baker"
|
|
528
|
+
/>
|
|
529
|
+
<Avatar
|
|
530
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
531
|
+
size="xs"
|
|
532
|
+
src="https://www.untitledui.com/images/avatars/lana-steiner?fm=webp&q=80&w=100"
|
|
533
|
+
alt="Lana Steiner"
|
|
534
|
+
/>
|
|
535
|
+
<Avatar
|
|
536
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
537
|
+
size="xs"
|
|
538
|
+
src="https://www.untitledui.com/images/avatars/demi-wilkinson?fm=webp&q=80&w=100"
|
|
539
|
+
alt="Demi Wilkinson"
|
|
540
|
+
/>
|
|
541
|
+
<Avatar
|
|
542
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
543
|
+
size="xs"
|
|
544
|
+
src="https://www.untitledui.com/images/avatars/candice-wu?fm=webp&q=80&w=100"
|
|
545
|
+
alt="Candice Wu"
|
|
546
|
+
/>
|
|
547
|
+
<Avatar
|
|
548
|
+
size="xs"
|
|
549
|
+
className="ring-[1.5px] ring-bg-primary"
|
|
550
|
+
placeholder={<span className="text-xs font-semibold text-quaternary">+5</span>}
|
|
551
|
+
/>
|
|
552
|
+
</div>
|
|
553
|
+
</Table.Cell>
|
|
554
|
+
<Table.Cell>
|
|
555
|
+
<ProgressBar labelPosition="right" value={item.licenseUse} />
|
|
556
|
+
</Table.Cell>
|
|
557
|
+
<Table.Cell className="px-4">
|
|
558
|
+
<div className="flex items-center justify-end">
|
|
559
|
+
<TableRowActionsDropdown />
|
|
560
|
+
</div>
|
|
561
|
+
</Table.Cell>
|
|
562
|
+
</Table.Row>
|
|
563
|
+
)}
|
|
564
|
+
</Table.Body>
|
|
565
|
+
</Table>
|
|
566
|
+
</TableCard.Root>
|
|
567
|
+
);
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
export const Table03DividerLine = () => {
|
|
571
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
572
|
+
column: "invoice",
|
|
573
|
+
direction: "ascending",
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
const sortedItems = useMemo(() => {
|
|
577
|
+
return invoices.items.sort((a, b) => {
|
|
578
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
579
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
580
|
+
|
|
581
|
+
// Compare numbers or booleans
|
|
582
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
583
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Compare strings
|
|
587
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
588
|
+
let cmp = first.localeCompare(second);
|
|
589
|
+
if (sortDescriptor.direction === "descending") {
|
|
590
|
+
cmp *= -1;
|
|
591
|
+
}
|
|
592
|
+
return cmp;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return 0;
|
|
596
|
+
});
|
|
597
|
+
}, [sortDescriptor]);
|
|
598
|
+
|
|
599
|
+
const getInitials = (name: string) => {
|
|
600
|
+
return name
|
|
601
|
+
.split(" ")
|
|
602
|
+
.map((n) => n[0])
|
|
603
|
+
.join("");
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
return (
|
|
607
|
+
<TableCard.Root>
|
|
608
|
+
<Table aria-label="Team members" selectionMode="multiple" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
609
|
+
<Table.Header>
|
|
610
|
+
<Table.Head id="id" label="Invoice" isRowHeader allowsSorting />
|
|
611
|
+
<Table.Head id="date" label="Date" allowsSorting />
|
|
612
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
613
|
+
<Table.Head id="customer" label="Customer" />
|
|
614
|
+
<Table.Head id="purchase" label="Purchase" className="md:hidden xl:table-cell" />
|
|
615
|
+
<Table.Head id="actions" />
|
|
616
|
+
</Table.Header>
|
|
617
|
+
<Table.Body items={sortedItems}>
|
|
618
|
+
{(item) => (
|
|
619
|
+
<Table.Row id={item.id}>
|
|
620
|
+
<Table.Cell className="font-medium text-primary">#{item.id}</Table.Cell>
|
|
621
|
+
<Table.Cell className="whitespace-nowrap">
|
|
622
|
+
{new Date(item.date).toLocaleString(undefined, { year: "numeric", month: "short", day: "numeric" })}
|
|
623
|
+
</Table.Cell>
|
|
624
|
+
<Table.Cell>
|
|
625
|
+
{item.status === "paid" ? (
|
|
626
|
+
<BadgeWithIcon size="sm" color="success" iconLeading={Check} className="capitalize">
|
|
627
|
+
{item.status}
|
|
628
|
+
</BadgeWithIcon>
|
|
629
|
+
) : item.status === "refunded" ? (
|
|
630
|
+
<BadgeWithIcon size="sm" color="gray" iconLeading={ReverseLeft} className="capitalize">
|
|
631
|
+
{item.status}
|
|
632
|
+
</BadgeWithIcon>
|
|
633
|
+
) : (
|
|
634
|
+
<BadgeWithIcon size="sm" color="error" iconLeading={X} className="capitalize">
|
|
635
|
+
{item.status}
|
|
636
|
+
</BadgeWithIcon>
|
|
637
|
+
)}
|
|
638
|
+
</Table.Cell>
|
|
639
|
+
<Table.Cell>
|
|
640
|
+
<div className="flex items-center gap-3">
|
|
641
|
+
<Avatar initials={getInitials(item.customer.name)} src={item.customer.avatarUrl} alt={item.customer.name} size="md" />
|
|
642
|
+
<div className="whitespace-nowrap">
|
|
643
|
+
<p className="text-sm font-medium text-primary">{item.customer.name}</p>
|
|
644
|
+
<p className="text-sm text-tertiary">{item.customer.email}</p>
|
|
645
|
+
</div>
|
|
646
|
+
</div>
|
|
647
|
+
</Table.Cell>
|
|
648
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.purchase}</Table.Cell>
|
|
649
|
+
<Table.Cell>
|
|
650
|
+
<div className="flex items-center justify-end gap-3">
|
|
651
|
+
<Button size="sm" color="link-gray">
|
|
652
|
+
Delete
|
|
653
|
+
</Button>
|
|
654
|
+
<Button size="sm" color="link-color">
|
|
655
|
+
Edit
|
|
656
|
+
</Button>
|
|
657
|
+
</div>
|
|
658
|
+
</Table.Cell>
|
|
659
|
+
</Table.Row>
|
|
660
|
+
)}
|
|
661
|
+
</Table.Body>
|
|
662
|
+
</Table>
|
|
663
|
+
<PaginationPageMinimalCenter page={1} total={10} className="px-4 py-3 md:px-6 md:pt-3 md:pb-4" />
|
|
664
|
+
</TableCard.Root>
|
|
665
|
+
);
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
export const Table03AlternatingFills = () => {
|
|
669
|
+
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
|
670
|
+
column: "invoice",
|
|
671
|
+
direction: "ascending",
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const sortedItems = useMemo(() => {
|
|
675
|
+
return invoices.items.sort((a, b) => {
|
|
676
|
+
const first = a[sortDescriptor.column as keyof typeof a];
|
|
677
|
+
const second = b[sortDescriptor.column as keyof typeof b];
|
|
678
|
+
|
|
679
|
+
// Compare numbers or booleans
|
|
680
|
+
if ((typeof first === "number" && typeof second === "number") || (typeof first === "boolean" && typeof second === "boolean")) {
|
|
681
|
+
return sortDescriptor.direction === "descending" ? second - first : first - second;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Compare strings
|
|
685
|
+
if (typeof first === "string" && typeof second === "string") {
|
|
686
|
+
let cmp = first.localeCompare(second);
|
|
687
|
+
if (sortDescriptor.direction === "descending") {
|
|
688
|
+
cmp *= -1;
|
|
689
|
+
}
|
|
690
|
+
return cmp;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return 0;
|
|
694
|
+
});
|
|
695
|
+
}, [sortDescriptor]);
|
|
696
|
+
|
|
697
|
+
const getInitials = (name: string) => {
|
|
698
|
+
return name
|
|
699
|
+
.split(" ")
|
|
700
|
+
.map((n) => n[0])
|
|
701
|
+
.join("");
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
return (
|
|
705
|
+
<TableCard.Root>
|
|
706
|
+
<Table aria-label="Team members" selectionMode="multiple" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
|
|
707
|
+
<Table.Header className="bg-primary">
|
|
708
|
+
<Table.Head id="id" label="Invoice" isRowHeader allowsSorting />
|
|
709
|
+
<Table.Head id="date" label="Date" allowsSorting />
|
|
710
|
+
<Table.Head id="status" label="Status" allowsSorting />
|
|
711
|
+
<Table.Head id="customer" label="Customer" />
|
|
712
|
+
<Table.Head id="purchase" label="Purchase" className="md:hidden xl:table-cell" />
|
|
713
|
+
<Table.Head id="actions" />
|
|
714
|
+
</Table.Header>
|
|
715
|
+
<Table.Body items={sortedItems}>
|
|
716
|
+
{(item) => (
|
|
717
|
+
<Table.Row id={item.id} className="odd:bg-secondary_subtle">
|
|
718
|
+
<Table.Cell className="font-medium text-primary">#{item.id}</Table.Cell>
|
|
719
|
+
<Table.Cell className="whitespace-nowrap">{item.date}</Table.Cell>
|
|
720
|
+
<Table.Cell>
|
|
721
|
+
{item.status === "paid" ? (
|
|
722
|
+
<BadgeWithIcon size="sm" color="success" iconLeading={Check} className="capitalize">
|
|
723
|
+
{item.status}
|
|
724
|
+
</BadgeWithIcon>
|
|
725
|
+
) : item.status === "refunded" ? (
|
|
726
|
+
<BadgeWithIcon size="sm" color="gray" iconLeading={ReverseLeft} className="capitalize">
|
|
727
|
+
{item.status}
|
|
728
|
+
</BadgeWithIcon>
|
|
729
|
+
) : (
|
|
730
|
+
<BadgeWithIcon size="sm" color="error" iconLeading={X} className="capitalize">
|
|
731
|
+
{item.status}
|
|
732
|
+
</BadgeWithIcon>
|
|
733
|
+
)}
|
|
734
|
+
</Table.Cell>
|
|
735
|
+
<Table.Cell>
|
|
736
|
+
<div className="flex items-center gap-3">
|
|
737
|
+
<Avatar initials={getInitials(item.customer.name)} src={item.customer.avatarUrl} alt={item.customer.name} size="md" />
|
|
738
|
+
<div className="whitespace-nowrap">
|
|
739
|
+
<p className="text-sm font-medium text-primary">{item.customer.name}</p>
|
|
740
|
+
<p className="text-sm text-tertiary">{item.customer.email}</p>
|
|
741
|
+
</div>
|
|
742
|
+
</div>
|
|
743
|
+
</Table.Cell>
|
|
744
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.purchase}</Table.Cell>
|
|
745
|
+
<Table.Cell>
|
|
746
|
+
<div className="flex items-center justify-end gap-3">
|
|
747
|
+
<Button size="sm" color="link-gray">
|
|
748
|
+
Delete
|
|
749
|
+
</Button>
|
|
750
|
+
<Button size="sm" color="link-color">
|
|
751
|
+
Edit
|
|
752
|
+
</Button>
|
|
753
|
+
</div>
|
|
754
|
+
</Table.Cell>
|
|
755
|
+
</Table.Row>
|
|
756
|
+
)}
|
|
757
|
+
</Table.Body>
|
|
758
|
+
</Table>
|
|
759
|
+
<PaginationPageMinimalCenter page={1} total={10} className="px-4 py-3 md:px-6 md:pt-3 md:pb-4" />
|
|
760
|
+
</TableCard.Root>
|
|
761
|
+
);
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
export const Table04DividerLine = () => {
|
|
765
|
+
return (
|
|
766
|
+
<TableCard.Root>
|
|
767
|
+
<TableCard.Header
|
|
768
|
+
title="Files uploaded"
|
|
769
|
+
className="pb-5"
|
|
770
|
+
contentTrailing={
|
|
771
|
+
<div className="flex items-center gap-3">
|
|
772
|
+
<Button size="md" color="secondary">
|
|
773
|
+
Download all
|
|
774
|
+
</Button>
|
|
775
|
+
<Button size="md" iconLeading={UploadCloud02}>
|
|
776
|
+
Upload
|
|
777
|
+
</Button>
|
|
778
|
+
</div>
|
|
779
|
+
}
|
|
780
|
+
/>
|
|
781
|
+
<Table aria-label="Team members" selectionMode="multiple">
|
|
782
|
+
<Table.Header>
|
|
783
|
+
<Table.Head id="name" label="File name" isRowHeader />
|
|
784
|
+
<Table.Head id="size" label="File size" />
|
|
785
|
+
<Table.Head id="uploadedAt" label="Date uploaded" />
|
|
786
|
+
<Table.Head id="updatedAt" label="Last updated" className="md:hidden xl:table-cell" />
|
|
787
|
+
<Table.Head id="uploadedBy" label="Uploaded by" />
|
|
788
|
+
<Table.Head id="actions" />
|
|
789
|
+
</Table.Header>
|
|
790
|
+
<Table.Body items={uploadedFiles.items}>
|
|
791
|
+
{(item) => (
|
|
792
|
+
<Table.Row id={item.name}>
|
|
793
|
+
<Table.Cell>
|
|
794
|
+
<div className="flex items-center gap-3">
|
|
795
|
+
<FileIcon type={item.name.split(".")[1]} theme="light" className="size-10 dark:hidden" />
|
|
796
|
+
<FileIcon type={item.name.split(".")[1]} theme="dark" className="size-10 not-dark:hidden" />
|
|
797
|
+
|
|
798
|
+
<div className="whitespace-nowrap">
|
|
799
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
800
|
+
<p className="text-sm text-tertiary">{item.size}</p>
|
|
801
|
+
</div>
|
|
802
|
+
</div>
|
|
803
|
+
</Table.Cell>
|
|
804
|
+
<Table.Cell className="whitespace-nowrap">{item.size}</Table.Cell>
|
|
805
|
+
<Table.Cell className="whitespace-nowrap">{item.uploadedAt}</Table.Cell>
|
|
806
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.updatedAt}</Table.Cell>
|
|
807
|
+
<Table.Cell className="whitespace-nowrap">{item.uploadedBy}</Table.Cell>
|
|
808
|
+
<Table.Cell className="px-4">
|
|
809
|
+
<div className="flex items-center justify-end">
|
|
810
|
+
<TableRowActionsDropdown />
|
|
811
|
+
</div>
|
|
812
|
+
</Table.Cell>
|
|
813
|
+
</Table.Row>
|
|
814
|
+
)}
|
|
815
|
+
</Table.Body>
|
|
816
|
+
</Table>
|
|
817
|
+
</TableCard.Root>
|
|
818
|
+
);
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
export const Table04AlternatingFills = () => {
|
|
822
|
+
return (
|
|
823
|
+
<TableCard.Root>
|
|
824
|
+
<TableCard.Header
|
|
825
|
+
title="Files uploaded"
|
|
826
|
+
badge="10/20 seats"
|
|
827
|
+
contentTrailing={
|
|
828
|
+
<div className="flex items-center gap-3">
|
|
829
|
+
<Button size="md" color="secondary">
|
|
830
|
+
Download all
|
|
831
|
+
</Button>
|
|
832
|
+
<Button size="md" iconLeading={UploadCloud02}>
|
|
833
|
+
Upload
|
|
834
|
+
</Button>
|
|
835
|
+
</div>
|
|
836
|
+
}
|
|
837
|
+
/>
|
|
838
|
+
<Table aria-label="Team members" selectionMode="multiple">
|
|
839
|
+
<Table.Header className="bg-primary">
|
|
840
|
+
<Table.Head id="name" label="File name" isRowHeader />
|
|
841
|
+
<Table.Head id="size" label="File size" />
|
|
842
|
+
<Table.Head id="uploadedAt" label="Date uploaded" />
|
|
843
|
+
<Table.Head id="updatedAt" label="Last updated" className="md:hidden xl:table-cell" />
|
|
844
|
+
<Table.Head id="uploadedBy" label="Uploaded by" />
|
|
845
|
+
<Table.Head id="actions" />
|
|
846
|
+
</Table.Header>
|
|
847
|
+
<Table.Body items={uploadedFiles.items}>
|
|
848
|
+
{(item) => (
|
|
849
|
+
<Table.Row id={item.name} className="odd:bg-secondary_subtle">
|
|
850
|
+
<Table.Cell>
|
|
851
|
+
<div className="flex items-center gap-3">
|
|
852
|
+
<FileIcon type={item.name.split(".")[1]} theme="light" className="size-10 dark:hidden" />
|
|
853
|
+
<FileIcon type={item.name.split(".")[1]} theme="dark" className="size-10 not-dark:hidden" />
|
|
854
|
+
|
|
855
|
+
<div className="whitespace-nowrap">
|
|
856
|
+
<p className="text-sm font-medium text-primary">{item.name}</p>
|
|
857
|
+
<p className="text-sm text-tertiary">{item.size}</p>
|
|
858
|
+
</div>
|
|
859
|
+
</div>
|
|
860
|
+
</Table.Cell>
|
|
861
|
+
<Table.Cell className="whitespace-nowrap">{item.size}</Table.Cell>
|
|
862
|
+
<Table.Cell className="whitespace-nowrap">{item.uploadedAt}</Table.Cell>
|
|
863
|
+
<Table.Cell className="whitespace-nowrap md:hidden xl:table-cell">{item.updatedAt}</Table.Cell>
|
|
864
|
+
<Table.Cell className="whitespace-nowrap">{item.uploadedBy}</Table.Cell>
|
|
865
|
+
<Table.Cell className="px-4">
|
|
866
|
+
<div className="flex items-center justify-end">
|
|
867
|
+
<TableRowActionsDropdown />
|
|
868
|
+
</div>
|
|
869
|
+
</Table.Cell>
|
|
870
|
+
</Table.Row>
|
|
871
|
+
)}
|
|
872
|
+
</Table.Body>
|
|
873
|
+
</Table>
|
|
874
|
+
</TableCard.Root>
|
|
875
|
+
);
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
export const TableNoVendorsFound = () => {
|
|
879
|
+
return (
|
|
880
|
+
<TableCard.Root>
|
|
881
|
+
<TableCard.Header
|
|
882
|
+
title="Vendor movements"
|
|
883
|
+
badge="240 vendors"
|
|
884
|
+
description="Keep track of vendor and their security ratings."
|
|
885
|
+
contentTrailing={
|
|
886
|
+
<>
|
|
887
|
+
<div className="flex gap-3 md:pr-9">
|
|
888
|
+
<Button color="secondary" size="md" iconLeading={UploadCloud02}>
|
|
889
|
+
Import
|
|
890
|
+
</Button>
|
|
891
|
+
<Button size="md" iconLeading={Plus}>
|
|
892
|
+
Add vendor
|
|
893
|
+
</Button>
|
|
894
|
+
</div>
|
|
895
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
896
|
+
<TableRowActionsDropdown />
|
|
897
|
+
</div>
|
|
898
|
+
</>
|
|
899
|
+
}
|
|
900
|
+
/>
|
|
901
|
+
|
|
902
|
+
<div className="flex justify-between gap-4 border-b border-secondary px-4 py-3 md:px-6">
|
|
903
|
+
<ButtonGroup defaultSelectedKeys={["all"]}>
|
|
904
|
+
<ButtonGroupItem id="all">View all</ButtonGroupItem>
|
|
905
|
+
<ButtonGroupItem id="monitored">Monitored</ButtonGroupItem>
|
|
906
|
+
<ButtonGroupItem id="unmonitored">Unmonitored</ButtonGroupItem>
|
|
907
|
+
</ButtonGroup>
|
|
908
|
+
|
|
909
|
+
<div className="hidden gap-3 md:flex">
|
|
910
|
+
<Input icon={SearchLg} aria-label="Search" placeholder="Search" className="w-70" />
|
|
911
|
+
<Button size="md" color="secondary" iconLeading={FilterLines}>
|
|
912
|
+
Filters
|
|
913
|
+
</Button>
|
|
914
|
+
</div>
|
|
915
|
+
</div>
|
|
916
|
+
|
|
917
|
+
<div className="flex items-center justify-center overflow-hidden px-8 pt-10 pb-12">
|
|
918
|
+
<EmptyState size="sm">
|
|
919
|
+
<EmptyState.Header pattern="circle">
|
|
920
|
+
<EmptyState.FeaturedIcon color="gray" theme="modern-neue" />
|
|
921
|
+
</EmptyState.Header>
|
|
922
|
+
|
|
923
|
+
<EmptyState.Content>
|
|
924
|
+
<EmptyState.Title>No vendors found</EmptyState.Title>
|
|
925
|
+
<EmptyState.Description>
|
|
926
|
+
Your search “Stripe” did not match any vendors. Please try again or create add a new vendor.
|
|
927
|
+
</EmptyState.Description>
|
|
928
|
+
</EmptyState.Content>
|
|
929
|
+
|
|
930
|
+
<EmptyState.Footer>
|
|
931
|
+
<Button size="md" color="secondary">
|
|
932
|
+
Clear search
|
|
933
|
+
</Button>
|
|
934
|
+
<Button size="md" iconLeading={Plus}>
|
|
935
|
+
New project
|
|
936
|
+
</Button>
|
|
937
|
+
</EmptyState.Footer>
|
|
938
|
+
</EmptyState>
|
|
939
|
+
</div>
|
|
940
|
+
|
|
941
|
+
<div className="flex items-center justify-between border-t border-secondary px-6 pt-3 pb-4">
|
|
942
|
+
<span className="text-sm">Page 1 of 10</span>
|
|
943
|
+
<div className="flex gap-3">
|
|
944
|
+
<Button color="secondary">Previous</Button>
|
|
945
|
+
<Button color="secondary">Next</Button>
|
|
946
|
+
</div>
|
|
947
|
+
</div>
|
|
948
|
+
</TableCard.Root>
|
|
949
|
+
);
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
export const TableStartByUploadingFile = () => {
|
|
953
|
+
return (
|
|
954
|
+
<TableCard.Root>
|
|
955
|
+
<TableCard.Header
|
|
956
|
+
title="Files uploaded"
|
|
957
|
+
contentTrailing={
|
|
958
|
+
<div className="flex items-center">
|
|
959
|
+
<Button size="md" iconLeading={UploadCloud02}>
|
|
960
|
+
Upload
|
|
961
|
+
</Button>
|
|
962
|
+
</div>
|
|
963
|
+
}
|
|
964
|
+
/>
|
|
965
|
+
|
|
966
|
+
<div className="flex items-center justify-center overflow-hidden px-8 pt-10 pb-12">
|
|
967
|
+
<EmptyState size="sm">
|
|
968
|
+
<EmptyState.Header pattern="grid">
|
|
969
|
+
<EmptyState.Illustration type="cloud">
|
|
970
|
+
<UploadCloud02 />
|
|
971
|
+
</EmptyState.Illustration>
|
|
972
|
+
</EmptyState.Header>
|
|
973
|
+
|
|
974
|
+
<EmptyState.Content>
|
|
975
|
+
<EmptyState.Title>Start by uploading a file</EmptyState.Title>
|
|
976
|
+
<EmptyState.Description>
|
|
977
|
+
Any assets used in projects will live here. <br />
|
|
978
|
+
Start creating by uploading your files.
|
|
979
|
+
</EmptyState.Description>
|
|
980
|
+
</EmptyState.Content>
|
|
981
|
+
|
|
982
|
+
<EmptyState.Footer>
|
|
983
|
+
<Button size="md" iconLeading={Plus}>
|
|
984
|
+
New project
|
|
985
|
+
</Button>
|
|
986
|
+
</EmptyState.Footer>
|
|
987
|
+
</EmptyState>
|
|
988
|
+
</div>
|
|
989
|
+
</TableCard.Root>
|
|
990
|
+
);
|
|
991
|
+
};
|
|
992
|
+
|
|
993
|
+
export const TableSomethingWentWrong = () => {
|
|
994
|
+
return (
|
|
995
|
+
<TableCard.Root>
|
|
996
|
+
<TableCard.Header
|
|
997
|
+
title="Team members"
|
|
998
|
+
badge="100 users"
|
|
999
|
+
contentTrailing={
|
|
1000
|
+
<div className="absolute top-5 right-4 md:right-6">
|
|
1001
|
+
<TableRowActionsDropdown />
|
|
1002
|
+
</div>
|
|
1003
|
+
}
|
|
1004
|
+
/>
|
|
1005
|
+
|
|
1006
|
+
<div className="flex items-center justify-center overflow-hidden px-8 pt-10 pb-12">
|
|
1007
|
+
<EmptyState size="sm">
|
|
1008
|
+
<EmptyState.Header pattern="circle">
|
|
1009
|
+
<EmptyState.FeaturedIcon color="error" theme="light" icon={AlertCircle} />
|
|
1010
|
+
</EmptyState.Header>
|
|
1011
|
+
|
|
1012
|
+
<EmptyState.Content>
|
|
1013
|
+
<EmptyState.Title>Something went wrong...</EmptyState.Title>
|
|
1014
|
+
<EmptyState.Description>
|
|
1015
|
+
We had some trouble loading this page. Please refresh the page or{" "}
|
|
1016
|
+
<a
|
|
1017
|
+
href="#"
|
|
1018
|
+
className="rounded-xs underline underline-offset-2 outline-focus-ring focus-visible:outline-2 focus-visible:outline-offset-2"
|
|
1019
|
+
>
|
|
1020
|
+
get in touch
|
|
1021
|
+
</a>{" "}
|
|
1022
|
+
for support.
|
|
1023
|
+
</EmptyState.Description>
|
|
1024
|
+
</EmptyState.Content>
|
|
1025
|
+
|
|
1026
|
+
<EmptyState.Footer>
|
|
1027
|
+
<Button size="md" color="secondary">
|
|
1028
|
+
Clear search
|
|
1029
|
+
</Button>
|
|
1030
|
+
<Button size="md" iconLeading={Plus}>
|
|
1031
|
+
New project
|
|
1032
|
+
</Button>
|
|
1033
|
+
</EmptyState.Footer>
|
|
1034
|
+
</EmptyState>
|
|
1035
|
+
</div>
|
|
1036
|
+
</TableCard.Root>
|
|
1037
|
+
);
|
|
1038
|
+
};
|