@xenide-io/the-old-ui-theme 0.3.0 → 0.3.2

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 (89) hide show
  1. package/dist/chunk-5HSOBJ4F.mjs +5968 -0
  2. package/dist/{index-D1RTT2Ap.d.mts → index-BgG8Homu.d.mts} +419 -2
  3. package/dist/{index-D1RTT2Ap.d.ts → index-BgG8Homu.d.ts} +419 -2
  4. package/dist/index.d.mts +198 -95
  5. package/dist/index.d.ts +198 -95
  6. package/dist/index.js +2995 -1136
  7. package/dist/index.mjs +629 -735
  8. package/dist/ui.d.mts +1 -1
  9. package/dist/ui.d.ts +1 -1
  10. package/dist/ui.js +1986 -156
  11. package/dist/ui.mjs +76 -3
  12. package/package.json +4 -14
  13. package/src/app/globals.css +976 -2
  14. package/src/components/charts/index.ts +9 -8
  15. package/src/components/charts/quill/BarChart.tsx +85 -0
  16. package/src/components/charts/quill/FunnelChart.tsx +49 -0
  17. package/src/components/charts/quill/InsightShell.tsx +27 -0
  18. package/src/components/charts/quill/MetricCard.tsx +44 -0
  19. package/src/components/charts/quill/PieChart.tsx +81 -0
  20. package/src/components/charts/quill/Sparkline.tsx +57 -0
  21. package/src/components/charts/quill/TimeSeriesLineChart.tsx +62 -0
  22. package/src/components/charts/quill/index.ts +9 -0
  23. package/src/components/icons/icons.tsx +2 -0
  24. package/src/components/icons/index.ts +3 -0
  25. package/src/components/icons/lemon-brand-icons.tsx +16 -0
  26. package/src/components/icons/lemon-category-icons.tsx +72 -0
  27. package/src/components/icons/lemon-icons.tsx +57 -0
  28. package/src/components/sections/IconShowcase.tsx +110 -7
  29. package/src/components/sections/NewComponentsShowcase.tsx +1052 -0
  30. package/src/components/sections/ProductLayoutsShowcase.tsx +57 -117
  31. package/src/components/sections/QuillChartShowcase.tsx +92 -0
  32. package/src/components/sections/QuillDashboardShowcase.tsx +149 -0
  33. package/src/components/sections/SidebarShowcase.tsx +152 -0
  34. package/src/components/sections/TableShowcase.tsx +2 -0
  35. package/src/components/sections/TooltipShowcase.tsx +19 -25
  36. package/src/components/ui/AlertDialog.tsx +62 -0
  37. package/src/components/ui/AppLayout.tsx +27 -0
  38. package/src/components/ui/Autocomplete.tsx +106 -0
  39. package/src/components/ui/Banner.tsx +63 -0
  40. package/src/components/ui/ButtonGroup.tsx +16 -0
  41. package/src/components/ui/Chip.tsx +46 -0
  42. package/src/components/ui/Collapsible.tsx +46 -0
  43. package/src/components/ui/Combobox.tsx +119 -0
  44. package/src/components/ui/ContextMenu.tsx +81 -0
  45. package/src/components/ui/DataTable.tsx +133 -0
  46. package/src/components/ui/DatePicker.tsx +96 -0
  47. package/src/components/ui/Dialog.tsx +75 -0
  48. package/src/components/ui/Divider.tsx +39 -0
  49. package/src/components/ui/Dot.tsx +32 -0
  50. package/src/components/ui/InputGroup.tsx +16 -0
  51. package/src/components/ui/Lettermark.tsx +47 -0
  52. package/src/components/ui/Link.tsx +32 -0
  53. package/src/components/ui/LoadingBar.tsx +25 -0
  54. package/src/components/ui/Menubar.tsx +66 -0
  55. package/src/components/ui/Metric.tsx +34 -0
  56. package/src/components/ui/NumberField.tsx +76 -0
  57. package/src/components/ui/Popover.tsx +73 -0
  58. package/src/components/ui/ProgressCircle.tsx +63 -0
  59. package/src/components/ui/Resizable.tsx +71 -0
  60. package/src/components/ui/Row.tsx +51 -0
  61. package/src/components/ui/ScrollArea.tsx +54 -0
  62. package/src/components/ui/Sidebar.tsx +77 -0
  63. package/src/components/ui/Snack.tsx +48 -0
  64. package/src/components/ui/Spinner.tsx +30 -0
  65. package/src/components/ui/Splotch.tsx +33 -0
  66. package/src/components/ui/Table.tsx +2 -0
  67. package/src/components/ui/Tag.tsx +65 -0
  68. package/src/components/ui/Toggle.tsx +62 -0
  69. package/src/components/ui/Tooltip.test.tsx +58 -0
  70. package/src/components/ui/Tooltip.tsx +211 -0
  71. package/src/components/ui/Widget.tsx +31 -0
  72. package/src/components/ui/index.ts +275 -21
  73. package/dist/chunk-FDMD3IIN.mjs +0 -3831
  74. package/src/components/charts/ph-insight-charts.tsx +0 -162
  75. package/src/components/dashboard/DashboardFiltersBar.tsx +0 -19
  76. package/src/components/dashboard/DashboardGrid.tsx +0 -23
  77. package/src/components/dashboard/DashboardInsightPlaceholder.tsx +0 -37
  78. package/src/components/dashboard/DashboardKpiCard.tsx +0 -25
  79. package/src/components/dashboard/DashboardToolbar.tsx +0 -23
  80. package/src/components/dashboard/DashboardWell.tsx +0 -10
  81. package/src/components/dashboard/InsightMiniCard.tsx +0 -26
  82. package/src/components/dashboard/InsightShell.tsx +0 -37
  83. package/src/components/dashboard/InsightShellHeader.tsx +0 -22
  84. package/src/components/dashboard/MiniTrendBars.tsx +0 -51
  85. package/src/components/dashboard/index.ts +0 -31
  86. package/src/components/dashboard/types.ts +0 -9
  87. package/src/components/sections/ChartShowcase.tsx +0 -190
  88. package/src/components/sections/DashboardShowcase.tsx +0 -191
  89. package/src/components/sections/StatShowcase.tsx +0 -129
@@ -0,0 +1,1052 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import {
5
+ Banner, Divider, Tag, ProgressCircle, Row, Widget,
6
+ Lettermark, Splotch, Popover, LoadingBar, Link,
7
+ Spinner, Snack, Combobox, Autocomplete, ContextMenu,
8
+ Resizable, ScrollArea, NumberField, InputGroup, ButtonGroup,
9
+ ToggleButton, ToggleGroup, Menubar, AlertDialog, Dot,
10
+ Collapsible, Metric, Chip, DataTable, DatePicker,
11
+ ComponentDocs, ShowcaseWrapper,
12
+ Button, Card, Badge, Dialog, Input, Checkbox, Textarea, Select,
13
+ } from "@/components/ui";
14
+ import { Bell, Sliders, User, Search, Plus } from "lucide-react";
15
+
16
+ const bannerCode = `import { Banner } from "@xenide-io/the-old-ui-theme";
17
+
18
+ <Banner type="info">You are viewing read-only data.</Banner>
19
+ <Banner type="success" onClose={() => {}}>Export completed successfully.</Banner>
20
+ <Banner type="warning">Your trial ends in 3 days.</Banner>
21
+ <Banner type="danger">Pipeline disconnected — check credentials.</Banner>`;
22
+
23
+ const tagCode = `import { Tag } from "@xenide-io/the-old-ui-theme";
24
+
25
+ <Tag type="primary">Beta</Tag>
26
+ <Tag type="success" closable>Approved</Tag>
27
+ <Tag type="warning">Pending</Tag>
28
+ <Tag type="danger">Failed</Tag>`;
29
+
30
+ const dividerCode = `import { Divider } from "@xenide-io/the-old-ui-theme";
31
+
32
+ <Divider />
33
+ <Divider dashed />
34
+ <Divider label="OR" />
35
+ <Divider vertical />`;
36
+
37
+ const progressCircleCode = `import { ProgressCircle } from "@xenide-io/the-old-ui-theme";
38
+
39
+ <ProgressCircle progress={0.75} />
40
+ <ProgressCircle progress={0.5} size={60}>
41
+ <span>50%</span>
42
+ </ProgressCircle>`;
43
+
44
+ const rowCode = `import { Row } from "@xenide-io/the-old-ui-theme";
45
+ import { User, Sliders } from "lucide-react";
46
+
47
+ <Row icon={<User className="h-4 w-4" />}>User profile</Row>
48
+ <Row sideIcon={<Sliders className="h-4 w-4" />}>Settings</Row>`;
49
+
50
+ const widgetCode = `import { Widget } from "@xenide-io/the-old-ui-theme";
51
+
52
+ <Widget title="Active Users" onClose={() => {}}>
53
+ Content here
54
+ </Widget>`;
55
+
56
+ const lettermarkCode = `import { Lettermark } from "@xenide-io/the-old-ui-theme";
57
+
58
+ <Lettermark name="PostHog" />
59
+ <Lettermark name="42" />
60
+ <Lettermark name="A" rounded outlined />`;
61
+
62
+ const splotchCode = `import { Splotch } from "@xenide-io/the-old-ui-theme";
63
+
64
+ <Splotch color="purple" />
65
+ <Splotch color="blue" />
66
+ <Splotch color="green" />`;
67
+
68
+ const popoverCode = `import { Popover } from "@xenide-io/the-old-ui-theme";
69
+
70
+ <Popover trigger={<Button>Open</Button>}>
71
+ Popover content
72
+ </Popover>`;
73
+
74
+ const loadingBarCode = `import { LoadingBar } from "@xenide-io/the-old-ui-theme";
75
+
76
+ <LoadingBar active />`;
77
+
78
+ const linkCode = `import { Link } from "@xenide-io/the-old-ui-theme";
79
+
80
+ <Link href="/docs">Documentation</Link>`;
81
+
82
+ const spinnerCode = `import { Spinner } from "@xenide-io/the-old-ui-theme";
83
+
84
+ <Spinner />
85
+ <Spinner size="lg" />`;
86
+
87
+ const snackCode = `import { Snack } from "@xenide-io/the-old-ui-theme";
88
+
89
+ <Snack>app.posthog.com</Snack>
90
+ <Snack type="pill" onClose={() => {}}>Filter applied</Snack>`;
91
+
92
+ export default function NewComponentsShowcase() {
93
+ const [dialogOpen, setDialogOpen] = useState(false);
94
+ const [loading, setLoading] = useState(false);
95
+
96
+ const toggleLoading = () => {
97
+ setLoading(true);
98
+ setTimeout(() => setLoading(false), 2000);
99
+ };
100
+
101
+ return (
102
+ <>
103
+ <ShowcaseWrapper
104
+ title="Banner"
105
+ description="Status banners for page-level alerts and notifications."
106
+ code={bannerCode}
107
+ filename="BannerExample.tsx"
108
+ docs={
109
+ <ComponentDocs
110
+ rows={[
111
+ { name: "type", type: "'info' | 'success' | 'warning' | 'danger' | 'ai'", defaultValue: "info", description: "Controls the banner colour." },
112
+ { name: "onClose", type: "() => void", description: "Shows a close button when provided." },
113
+ { name: "action", type: "ReactNode", description: "Optional action element (e.g. a button)." },
114
+ { name: "hideIcon", type: "boolean", defaultValue: "false", description: "Hides the type icon." },
115
+ { name: "square", type: "boolean", defaultValue: "false", description: "Removes border-radius." },
116
+ ]}
117
+ />
118
+ }
119
+ >
120
+ <div className="space-y-3">
121
+ <Banner type="info">You are viewing read-only data from a previous export.</Banner>
122
+ <Banner type="success" onClose={() => {}}>Export completed successfully. Download available now.</Banner>
123
+ <Banner type="warning">Your trial period ends in 3 days. Add a billing method to continue.</Banner>
124
+ <Banner type="danger">Pipeline disconnected — check your source credentials.</Banner>
125
+ <Banner type="ai">PostHog AI has identified 3 optimization opportunities.</Banner>
126
+ </div>
127
+ </ShowcaseWrapper>
128
+
129
+ <ShowcaseWrapper
130
+ title="Tag"
131
+ description="Compact labels for status, categories, and metadata."
132
+ code={tagCode}
133
+ filename="TagExample.tsx"
134
+ docs={
135
+ <ComponentDocs
136
+ rows={[
137
+ { name: "type", type: "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'muted' | 'highlight'", defaultValue: "default", description: "Semantic colour." },
138
+ { name: "size", type: "'sm' | 'md'", defaultValue: "md", description: "Tag size." },
139
+ { name: "icon", type: "ReactNode", description: "Leading icon." },
140
+ { name: "closable", type: "boolean", defaultValue: "false", description: "Shows a close button." },
141
+ { name: "onClose", type: "() => void", description: "Close callback." },
142
+ ]}
143
+ />
144
+ }
145
+ >
146
+ <div className="flex flex-wrap gap-2">
147
+ <Tag type="default">Default</Tag>
148
+ <Tag type="primary">Beta</Tag>
149
+ <Tag type="success">Live</Tag>
150
+ <Tag type="warning">Pending</Tag>
151
+ <Tag type="danger">Failed</Tag>
152
+ <Tag type="info">Info</Tag>
153
+ <Tag type="muted">Archived</Tag>
154
+ <Tag type="highlight">New</Tag>
155
+ <Tag type="success" closable onClose={() => {}}>Approved</Tag>
156
+ <Tag type="primary" size="sm">Small</Tag>
157
+ </div>
158
+ </ShowcaseWrapper>
159
+
160
+ <ShowcaseWrapper
161
+ title="Divider"
162
+ description="Separates content sections horizontally or vertically."
163
+ code={dividerCode}
164
+ filename="DividerExample.tsx"
165
+ docs={
166
+ <ComponentDocs
167
+ rows={[
168
+ { name: "vertical", type: "boolean", defaultValue: "false", description: "Render as a vertical divider." },
169
+ { name: "dashed", type: "boolean", defaultValue: "false", description: "Dashed line style." },
170
+ { name: "thick", type: "boolean", defaultValue: "false", description: "Thicker line." },
171
+ { name: "label", type: "string", description: "Shows a label inside the divider." },
172
+ ]}
173
+ />
174
+ }
175
+ >
176
+ <div className="space-y-6">
177
+ <div>
178
+ <p className="text-sm text-ph-subtle">Content above</p>
179
+ <Divider />
180
+ <p className="text-sm text-ph-subtle">Content below</p>
181
+ </div>
182
+ <Divider dashed />
183
+ <Divider label="OR" />
184
+ <div className="flex h-20 items-center gap-4">
185
+ <span className="text-sm text-ph-subtle">Left</span>
186
+ <Divider vertical />
187
+ <span className="text-sm text-ph-subtle">Right</span>
188
+ </div>
189
+ </div>
190
+ </ShowcaseWrapper>
191
+
192
+ <ShowcaseWrapper
193
+ title="Progress Circle"
194
+ description="Circular progress indicator with optional child content."
195
+ code={progressCircleCode}
196
+ filename="ProgressCircleExample.tsx"
197
+ docs={
198
+ <ComponentDocs
199
+ rows={[
200
+ { name: "progress", type: "number", defaultValue: "0", description: "Progress value between 0 and 1." },
201
+ { name: "size", type: "number", defaultValue: "40", description: "Diameter in pixels." },
202
+ { name: "strokeWidth", type: "number", description: "Stroke width override." },
203
+ { name: "children", type: "ReactNode", description: "Content rendered in the centre." },
204
+ ]}
205
+ />
206
+ }
207
+ >
208
+ <div className="flex flex-wrap items-end gap-8">
209
+ <div className="flex flex-col items-center gap-2">
210
+ <ProgressCircle progress={0.25} size={48} />
211
+ <span className="text-xs text-ph-mutedtext">25%</span>
212
+ </div>
213
+ <div className="flex flex-col items-center gap-2">
214
+ <ProgressCircle progress={0.5} size={48} />
215
+ <span className="text-xs text-ph-mutedtext">50%</span>
216
+ </div>
217
+ <div className="flex flex-col items-center gap-2">
218
+ <ProgressCircle progress={0.75} size={48} />
219
+ <span className="text-xs text-ph-mutedtext">75%</span>
220
+ </div>
221
+ <div className="flex flex-col items-center gap-2">
222
+ <ProgressCircle progress={1} size={48} />
223
+ <span className="text-xs text-ph-mutedtext">100%</span>
224
+ </div>
225
+ <div className="flex flex-col items-center gap-2">
226
+ <ProgressCircle progress={0.65} size={64}>
227
+ <span className="text-xs font-bold">65%</span>
228
+ </ProgressCircle>
229
+ <span className="text-xs text-ph-mutedtext">With label</span>
230
+ </div>
231
+ </div>
232
+ </ShowcaseWrapper>
233
+
234
+ <ShowcaseWrapper
235
+ title="Row"
236
+ description="Horizontal layout container with icon and side-icon slots."
237
+ code={rowCode}
238
+ filename="RowExample.tsx"
239
+ docs={
240
+ <ComponentDocs
241
+ rows={[
242
+ { name: "icon", type: "ReactElement", description: "Leading icon element." },
243
+ { name: "sideIcon", type: "ReactElement", description: "Trailing icon element." },
244
+ { name: "status", type: "'default' | 'success' | 'warning' | 'danger' | 'muted'", defaultValue: "default", description: "Semantic colour." },
245
+ { name: "fullWidth", type: "boolean", defaultValue: "false", description: "Takes full width." },
246
+ { name: "center", type: "boolean", defaultValue: "false", description: "Centers content." },
247
+ { name: "size", type: "'sm' | 'md' | 'lg'", defaultValue: "md", description: "Row size." },
248
+ ]}
249
+ />
250
+ }
251
+ >
252
+ <div className="space-y-3">
253
+ <Row icon={<User className="h-4 w-4" />}>User profile</Row>
254
+ <Row sideIcon={<Sliders className="h-4 w-4" />}>Settings</Row>
255
+ <Row icon={<Bell className="h-4 w-4" />} sideIcon={<Badge variant="danger">3</Badge>}>
256
+ Notifications
257
+ </Row>
258
+ <Row status="success" fullWidth className="rounded-md bg-ph-muted px-3 py-2">
259
+ Operation completed successfully
260
+ </Row>
261
+ <Row center fullWidth>
262
+ Centered content
263
+ </Row>
264
+ </div>
265
+ </ShowcaseWrapper>
266
+
267
+ <ShowcaseWrapper
268
+ title="Widget"
269
+ description="Panel with a distinct header and content area."
270
+ code={widgetCode}
271
+ filename="WidgetExample.tsx"
272
+ docs={
273
+ <ComponentDocs
274
+ rows={[
275
+ { name: "title", type: "ReactNode", description: "Widget header title." },
276
+ { name: "onClose", type: "() => void", description: "Shows close button." },
277
+ { name: "actions", type: "ReactNode", description: "Header action elements." },
278
+ ]}
279
+ />
280
+ }
281
+ >
282
+ <div className="grid gap-4 sm:grid-cols-2">
283
+ <Widget title="Active Users" onClose={() => {}}>
284
+ <div className="flex items-baseline gap-2">
285
+ <span className="text-2xl font-bold text-ph-ink">1,234</span>
286
+ <span className="text-xs text-ph-success">+12%</span>
287
+ </div>
288
+ <p className="mt-1 text-xs text-ph-mutedtext">Last 30 minutes</p>
289
+ </Widget>
290
+ <Widget title="Page Views" actions={<Tag type="primary">Live</Tag>}>
291
+ <div className="flex items-baseline gap-2">
292
+ <span className="text-2xl font-bold text-ph-ink">89.2k</span>
293
+ <span className="text-xs text-ph-mutedtext">today</span>
294
+ </div>
295
+ </Widget>
296
+ </div>
297
+ </ShowcaseWrapper>
298
+
299
+ <ShowcaseWrapper
300
+ title="Lettermark"
301
+ description="Avatar-style initial letter display."
302
+ code={lettermarkCode}
303
+ filename="LettermarkExample.tsx"
304
+ docs={
305
+ <ComponentDocs
306
+ rows={[
307
+ { name: "name", type: "string | number", description: "Text to derive initial from." },
308
+ { name: "index", type: "number", description: "Picks a deterministic colour." },
309
+ { name: "rounded", type: "boolean", description: "Circular shape." },
310
+ { name: "outlined", type: "boolean", description: "Outlined vs filled." },
311
+ { name: "size", type: "'xs' | 'sm' | 'md' | 'lg'", defaultValue: "md" },
312
+ ]}
313
+ />
314
+ }
315
+ >
316
+ <div className="flex flex-wrap items-center gap-4">
317
+ <Lettermark name="PostHog" index={0} />
318
+ <Lettermark name="Analytics" index={1} />
319
+ <Lettermark name="Experiments" index={2} />
320
+ <Lettermark name="Replay" index={3} rounded />
321
+ <Lettermark name="Flags" index={4} rounded />
322
+ <Lettermark name="A" outlined />
323
+ <Lettermark name="42" index={5} rounded outlined />
324
+ <div className="flex items-center gap-2">
325
+ <Lettermark name="XS" size="xs" index={6} />
326
+ <Lettermark name="MD" index={7} />
327
+ <Lettermark name="LG" size="lg" index={0} />
328
+ </div>
329
+ </div>
330
+ </ShowcaseWrapper>
331
+
332
+ <ShowcaseWrapper
333
+ title="Splotch"
334
+ description="Color swatch indicator for pickers and menus."
335
+ code={splotchCode}
336
+ filename="SplotchExample.tsx"
337
+ docs={
338
+ <ComponentDocs
339
+ rows={[
340
+ { name: "color", type: "'purple' | 'blue' | 'green' | 'black' | 'white' | 'orange' | 'red' | 'yellow'", description: "Splotch colour." },
341
+ ]}
342
+ />
343
+ }
344
+ >
345
+ <div className="flex flex-wrap items-center gap-3">
346
+ <Splotch color="purple" />
347
+ <Splotch color="blue" />
348
+ <Splotch color="green" />
349
+ <Splotch color="orange" />
350
+ <Splotch color="red" />
351
+ <Splotch color="yellow" />
352
+ <Splotch color="black" />
353
+ <Splotch color="white" />
354
+ </div>
355
+ </ShowcaseWrapper>
356
+
357
+ <ShowcaseWrapper
358
+ title="Popover"
359
+ description="Floating panel anchored to a trigger element."
360
+ code={popoverCode}
361
+ filename="PopoverExample.tsx"
362
+ docs={
363
+ <ComponentDocs
364
+ rows={[
365
+ { name: "trigger", type: "ReactNode", description: "Element that opens the popover." },
366
+ { name: "open", type: "boolean", description: "Controlled open state." },
367
+ { name: "onOpenChange", type: "(open) => void", description: "Open state change handler." },
368
+ { name: "placement", type: "'top' | 'bottom' | 'left' | 'right'", defaultValue: "bottom", description: "Popover placement." },
369
+ { name: "matchTriggerWidth", type: "boolean", defaultValue: "false", description: "Match trigger width." },
370
+ { name: "padded", type: "boolean", defaultValue: "true", description: "Add padding inside panel." },
371
+ ]}
372
+ />
373
+ }
374
+ >
375
+ <div className="flex flex-wrap gap-4">
376
+ <Popover trigger={<Button variant="secondary">Open popover</Button>}>
377
+ <div className="space-y-2 text-sm">
378
+ <p className="font-medium text-ph-ink">Popover Content</p>
379
+ <p className="text-ph-mutedtext">This is a basic popover with some content inside.</p>
380
+ </div>
381
+ </Popover>
382
+ <Popover trigger={<Button variant="primary">With list</Button>}>
383
+ <div className="space-y-1">
384
+ {["Profile", "Settings", "Help", "Log out"].map((item) => (
385
+ <button
386
+ key={item}
387
+ type="button"
388
+ className="w-full rounded-md px-3 py-1.5 text-left text-sm text-ph-subtle hover:bg-ph-muted hover:text-ph-ink"
389
+ >
390
+ {item}
391
+ </button>
392
+ ))}
393
+ </div>
394
+ </Popover>
395
+ </div>
396
+ </ShowcaseWrapper>
397
+
398
+ <ShowcaseWrapper
399
+ title="Loading Bar"
400
+ description="Thin indeterminate progress bar for page-level loading."
401
+ code={loadingBarCode}
402
+ filename="LoadingBarExample.tsx"
403
+ docs={
404
+ <ComponentDocs
405
+ rows={[
406
+ { name: "active", type: "boolean", defaultValue: "true", description: "Animates when active." },
407
+ ]}
408
+ />
409
+ }
410
+ >
411
+ <div className="space-y-3">
412
+ <LoadingBar active />
413
+ <LoadingBar active={false} />
414
+ <Button variant="primary" onClick={toggleLoading} loading={loading}>
415
+ {loading ? "Loading..." : "Trigger loading"}
416
+ </Button>
417
+ </div>
418
+ </ShowcaseWrapper>
419
+
420
+ <ShowcaseWrapper
421
+ title="Link"
422
+ description="Styled text link with brand colour and hover underline."
423
+ code={linkCode}
424
+ filename="LinkExample.tsx"
425
+ docs={
426
+ <ComponentDocs
427
+ rows={[
428
+ { name: "disabled", type: "boolean", defaultValue: "false", description: "Disables the link." },
429
+ { name: "href", type: "string", description: "Anchor href." },
430
+ ]}
431
+ />
432
+ }
433
+ >
434
+ <div className="flex flex-wrap items-center gap-4">
435
+ <Link href="#">Documentation</Link>
436
+ <Link href="#">API Reference</Link>
437
+ <Link href="#">Changelog</Link>
438
+ <Link href="#" disabled>Disabled link</Link>
439
+ </div>
440
+ </ShowcaseWrapper>
441
+
442
+ <ShowcaseWrapper
443
+ title="Spinner"
444
+ description="Animated loading spinner for inline loading states."
445
+ code={spinnerCode}
446
+ filename="SpinnerExample.tsx"
447
+ docs={
448
+ <ComponentDocs
449
+ rows={[
450
+ { name: "size", type: "'sm' | 'md' | 'lg'", defaultValue: "sm", description: "Spinner size." },
451
+ { name: "textColored", type: "boolean", defaultValue: "false", description: "Use text colour instead of brand." },
452
+ ]}
453
+ />
454
+ }
455
+ >
456
+ <div className="flex flex-wrap items-center gap-6">
457
+ <div className="flex flex-col items-center gap-2">
458
+ <Spinner size="sm" />
459
+ <span className="text-xs text-ph-mutedtext">Small</span>
460
+ </div>
461
+ <div className="flex flex-col items-center gap-2">
462
+ <Spinner size="md" />
463
+ <span className="text-xs text-ph-mutedtext">Medium</span>
464
+ </div>
465
+ <div className="flex flex-col items-center gap-2">
466
+ <Spinner size="lg" />
467
+ <span className="text-xs text-ph-mutedtext">Large</span>
468
+ </div>
469
+ <div className="flex flex-col items-center gap-2">
470
+ <Spinner textColored />
471
+ <span className="text-xs text-ph-mutedtext">Text colored</span>
472
+ </div>
473
+ </div>
474
+ </ShowcaseWrapper>
475
+
476
+ <ShowcaseWrapper
477
+ title="Snack"
478
+ description="Small chip for displaying removable filter values or selections."
479
+ code={snackCode}
480
+ filename="SnackExample.tsx"
481
+ docs={
482
+ <ComponentDocs
483
+ rows={[
484
+ { name: "type", type: "'regular' | 'pill'", defaultValue: "regular", description: "Shape variant." },
485
+ { name: "onClose", type: "() => void", description: "Shows close button." },
486
+ { name: "wrap", type: "boolean", defaultValue: "false", description: "Allows text wrapping." },
487
+ ]}
488
+ />
489
+ }
490
+ >
491
+ <div className="flex flex-wrap gap-2">
492
+ <Snack>app.posthog.com</Snack>
493
+ <Snack>production</Snack>
494
+ <Snack type="pill">Filter: last 7 days</Snack>
495
+ <Snack type="pill" onClose={() => {}}>Status: active</Snack>
496
+ <Snack onClose={() => {}}>user_123@example.com</Snack>
497
+ </div>
498
+ </ShowcaseWrapper>
499
+
500
+ <ShowcaseWrapper
501
+ title="Dialog"
502
+ description="Confirmation dialog built on Modal with confirm/cancel buttons."
503
+ code={`import { Dialog } from "@xenide-io/the-old-ui-theme";
504
+
505
+ <Dialog
506
+ title="Confirm deletion"
507
+ confirmText="Delete"
508
+ confirmProps={{ variant: "danger" }}
509
+ onConfirm={() => console.log("confirmed")}
510
+ onClose={() => {}}
511
+ >
512
+ Are you sure?
513
+ </Dialog>`}
514
+ filename="DialogExample.tsx"
515
+ docs={
516
+ <ComponentDocs
517
+ rows={[
518
+ { name: "title", type: "string", description: "Dialog title." },
519
+ { name: "onConfirm", type: "() => void | Promise<void>", description: "Confirm callback." },
520
+ { name: "onClose", type: "() => void", description: "Close callback." },
521
+ { name: "confirmText", type: "string", defaultValue: "Confirm", description: "Confirm button label." },
522
+ { name: "cancelText", type: "string", defaultValue: "Cancel", description: "Cancel button label." },
523
+ { name: "confirmProps", type: "Partial<ButtonProps>", description: "Override confirm button." },
524
+ ]}
525
+ />
526
+ }
527
+ >
528
+ <div className="flex flex-wrap gap-4">
529
+ <Button variant="primary" onClick={() => setDialogOpen(true)}>
530
+ Open dialog
531
+ </Button>
532
+ <Dialog
533
+ title="Confirm action"
534
+ isOpen={dialogOpen}
535
+ onClose={() => setDialogOpen(false)}
536
+ onConfirm={() => {}}
537
+ confirmText="Continue"
538
+ >
539
+ <p className="text-sm text-ph-subtle">
540
+ Are you sure you want to proceed with this action? This cannot be undone.
541
+ </p>
542
+ </Dialog>
543
+ </div>
544
+ </ShowcaseWrapper>
545
+
546
+ <ShowcaseWrapper
547
+ title="Combobox"
548
+ description="Searchable multi-select with removable chips."
549
+ code={`import { Combobox } from "@xenide-io/the-old-ui-theme";
550
+
551
+ <Combobox
552
+ options={[
553
+ { value: "1", label: "Option A" },
554
+ { value: "2", label: "Option B" },
555
+ ]}
556
+ value={["1"]}
557
+ onChange={(v) => console.log(v)}
558
+ />`}
559
+ filename="ComboboxExample.tsx"
560
+ docs={<ComponentDocs rows={[
561
+ { name: "options", type: "ComboboxOption[]", description: "Array of {value, label}." },
562
+ { name: "value", type: "string[]", description: "Selected values." },
563
+ { name: "onChange", type: "(value: string[]) => void", description: "Selection change handler." },
564
+ { name: "placeholder", type: "string", defaultValue: "Search..." },
565
+ ]} />}
566
+ >
567
+ <Combobox
568
+ options={[
569
+ { value: "react", label: "React" },
570
+ { value: "vue", label: "Vue" },
571
+ { value: "svelte", label: "Svelte" },
572
+ { value: "angular", label: "Angular" },
573
+ { value: "solid", label: "Solid" },
574
+ ]}
575
+ value={["react", "vue"]}
576
+ placeholder="Search frameworks..."
577
+ />
578
+ </ShowcaseWrapper>
579
+
580
+ <ShowcaseWrapper
581
+ title="Autocomplete"
582
+ description="Search input with filtered suggestions dropdown."
583
+ code={`import { Autocomplete } from "@xenide-io/the-old-ui-theme";
584
+
585
+ <Autocomplete
586
+ options={[
587
+ { value: "1", label: "Result A" },
588
+ { value: "2", label: "Result B" },
589
+ ]}
590
+ onSelect={(opt) => console.log(opt)}
591
+ />`}
592
+ filename="AutocompleteExample.tsx"
593
+ docs={<ComponentDocs rows={[
594
+ { name: "options", type: "AutocompleteOption[]", description: "Array of {value, label}." },
595
+ { name: "onSelect", type: "(option) => void", description: "Selection handler." },
596
+ ]} />}
597
+ >
598
+ <Autocomplete
599
+ options={[
600
+ { value: "1", label: "Dashboard" },
601
+ { value: "2", label: "Insights" },
602
+ { value: "3", label: "Experiments" },
603
+ { value: "4", label: "Feature Flags" },
604
+ ]}
605
+ placeholder="Search pages..."
606
+ />
607
+ </ShowcaseWrapper>
608
+
609
+ <ShowcaseWrapper
610
+ title="Context Menu"
611
+ description="Right-click triggered contextual menu."
612
+ code={`import { ContextMenu } from "@xenide-io/the-old-ui-theme";
613
+
614
+ <ContextMenu
615
+ items={[
616
+ { label: "Edit", onClick: () => {} },
617
+ { label: "Delete", onClick: () => {}, disabled: true },
618
+ ]}
619
+ >
620
+ <div className="p-8 border rounded">Right-click me</div>
621
+ </ContextMenu>`}
622
+ filename="ContextMenuExample.tsx"
623
+ docs={<ComponentDocs rows={[
624
+ { name: "items", type: "ContextMenuItem[]", description: "Menu items with label, onClick, disabled, separator, icon." },
625
+ ]} />}
626
+ >
627
+ <ContextMenu
628
+ items={[
629
+ { label: "Edit", onClick: () => alert("Edit") },
630
+ { label: "Duplicate", onClick: () => alert("Duplicate") },
631
+ { separator: true },
632
+ { label: "Delete", onClick: () => alert("Delete") },
633
+ ]}
634
+ >
635
+ <Card variant="elevated" className="p-8 text-center text-sm text-ph-mutedtext cursor-context-menu">
636
+ Right-click this area
637
+ </Card>
638
+ </ContextMenu>
639
+ </ShowcaseWrapper>
640
+
641
+ <ShowcaseWrapper
642
+ title="Resizable"
643
+ description="Drag-to-resize split panel layout."
644
+ code={`import { Resizable } from "@xenide-io/the-old-ui-theme";
645
+
646
+ <Resizable
647
+ left={<div>Left panel</div>}
648
+ right={<div>Right panel</div>}
649
+ defaultLeftWidth={40}
650
+ />`}
651
+ filename="ResizableExample.tsx"
652
+ docs={<ComponentDocs rows={[
653
+ { name: "left", type: "ReactNode", description: "Left panel content." },
654
+ { name: "right", type: "ReactNode", description: "Right panel content." },
655
+ { name: "defaultLeftWidth", type: "number", defaultValue: "50", description: "Initial left width percentage." },
656
+ { name: "minLeftWidth", type: "number", defaultValue: "20", description: "Minimum left width %." },
657
+ { name: "minRightWidth", type: "number", defaultValue: "20", description: "Minimum right width %." },
658
+ ]} />}
659
+ >
660
+ <div className="h-48 rounded-lg border border-ph-border overflow-hidden">
661
+ <Resizable
662
+ left={<div className="flex h-full items-center justify-center text-sm text-ph-mutedtext bg-ph-muted">Left panel</div>}
663
+ right={<div className="flex h-full items-center justify-center text-sm text-ph-mutedtext">Right panel</div>}
664
+ defaultLeftWidth={40}
665
+ />
666
+ </div>
667
+ </ShowcaseWrapper>
668
+
669
+ <ShowcaseWrapper
670
+ title="Scroll Area"
671
+ description="Scrollable container with edge shadow indicators."
672
+ code={`import { ScrollArea } from "@xenide-io/the-old-ui-theme";
673
+
674
+ <ScrollArea className="h-40">
675
+ {items.map((item) => <div key={item}>{item}</div>)}
676
+ </ScrollArea>`}
677
+ filename="ScrollAreaExample.tsx"
678
+ docs={<ComponentDocs rows={[
679
+ { name: "orientation", type: "'vertical' | 'horizontal' | 'both'", defaultValue: "vertical" },
680
+ ]} />}
681
+ >
682
+ <ScrollArea className="h-32 w-64 rounded-lg border border-ph-border">
683
+ <div className="space-y-2 p-3">
684
+ {Array.from({ length: 20 }, (_, i) => (
685
+ <div key={i} className="rounded-md bg-ph-muted px-3 py-2 text-sm text-ph-subtle">
686
+ Item {i + 1}
687
+ </div>
688
+ ))}
689
+ </div>
690
+ </ScrollArea>
691
+ </ShowcaseWrapper>
692
+
693
+ <ShowcaseWrapper
694
+ title="Number Field"
695
+ description="Numeric input with increment/decrement buttons."
696
+ code={`import { NumberField } from "@xenide-io/the-old-ui-theme";
697
+
698
+ <NumberField
699
+ value={5}
700
+ onChange={(v) => console.log(v)}
701
+ min={0}
702
+ max={100}
703
+ step={1}
704
+ />`}
705
+ filename="NumberFieldExample.tsx"
706
+ docs={<ComponentDocs rows={[
707
+ { name: "value", type: "number" },
708
+ { name: "onChange", type: "(value: number) => void" },
709
+ { name: "min", type: "number" },
710
+ { name: "max", type: "number" },
711
+ { name: "step", type: "number", defaultValue: "1" },
712
+ { name: "label", type: "string" },
713
+ ]} />}
714
+ >
715
+ <div className="flex flex-wrap gap-6">
716
+ <NumberField label="Quantity" min={0} max={99} />
717
+ <NumberField label="Timeout (s)" value={30} step={5} />
718
+ </div>
719
+ </ShowcaseWrapper>
720
+
721
+ <ShowcaseWrapper
722
+ title="Input Group"
723
+ description="Input with leading/trailing add-on elements."
724
+ code={`import { InputGroup, Input, Button } from "@xenide-io/the-old-ui-theme";
725
+
726
+ <InputGroup>
727
+ <span className="px-3 py-2 text-sm bg-ph-muted text-ph-subtle border-r border-ph-border">https://</span>
728
+ <input className="ph-input flex-1 border-0 rounded-none" />
729
+ <Button>Go</Button>
730
+ </InputGroup>`}
731
+ filename="InputGroupExample.tsx"
732
+ docs={<ComponentDocs rows={[
733
+ { name: "children", type: "ReactNode", description: "Elements to group together." },
734
+ ]} />}
735
+ >
736
+ <div className="space-y-3">
737
+ <InputGroup>
738
+ <span className="inline-flex items-center px-3 text-sm text-ph-mutedtext bg-ph-muted border-r border-ph-border">https://</span>
739
+ <Input placeholder="example.com" className="rounded-none border-0" />
740
+ </InputGroup>
741
+ <InputGroup>
742
+ <Input placeholder="Search..." className="rounded-none border-0" />
743
+ <Button variant="primary" className="rounded-none"><Search className="h-4 w-4" /></Button>
744
+ </InputGroup>
745
+ </div>
746
+ </ShowcaseWrapper>
747
+
748
+ <ShowcaseWrapper
749
+ title="Button Group"
750
+ description="Segmented button row with separators."
751
+ code={`import { ButtonGroup, Button } from "@xenide-io/the-old-ui-theme";
752
+
753
+ <ButtonGroup>
754
+ <Button variant="secondary">Left</Button>
755
+ <Button variant="secondary">Center</Button>
756
+ <Button variant="secondary">Right</Button>
757
+ </ButtonGroup>`}
758
+ filename="ButtonGroupExample.tsx"
759
+ docs={<ComponentDocs rows={[
760
+ { name: "children", type: "ReactNode", description: "Buttons to group." },
761
+ ]} />}
762
+ >
763
+ <ButtonGroup>
764
+ <Button variant="secondary" size="sm">Day</Button>
765
+ <Button variant="secondary" size="sm">Week</Button>
766
+ <Button variant="secondary" size="sm">Month</Button>
767
+ <Button variant="secondary" size="sm">Year</Button>
768
+ </ButtonGroup>
769
+ </ShowcaseWrapper>
770
+
771
+ <ShowcaseWrapper
772
+ title="Toggle Button"
773
+ description="Pressable toggle button for toolbars and stateful controls."
774
+ code={`import { ToggleButton, ToggleGroup } from "@xenide-io/the-old-ui-theme";
775
+
776
+ <ToggleButton pressed={true} onPressedChange={(p) => console.log(p)}>
777
+ Bold
778
+ </ToggleButton>`}
779
+ filename="ToggleButtonExample.tsx"
780
+ docs={<ComponentDocs rows={[
781
+ { name: "pressed", type: "boolean", defaultValue: "false" },
782
+ { name: "onPressedChange", type: "(pressed: boolean) => void" },
783
+ { name: "icon", type: "ReactNode", description: "Leading icon." },
784
+ ]} />}
785
+ >
786
+ <div className="space-y-4">
787
+ <div className="flex flex-wrap gap-2">
788
+ <ToggleButton pressed={true}>Bold</ToggleButton>
789
+ <ToggleButton>Italic</ToggleButton>
790
+ <ToggleButton>Underline</ToggleButton>
791
+ </div>
792
+ </div>
793
+ </ShowcaseWrapper>
794
+
795
+ <ShowcaseWrapper
796
+ title="Menubar"
797
+ description="Horizontal menu bar with dropdown submenus."
798
+ code={`import { Menubar } from "@xenide-io/the-old-ui-theme";
799
+
800
+ <Menubar
801
+ items={[
802
+ { label: "File", items: [{ label: "New" }, { label: "Open" }] },
803
+ { label: "Edit", items: [{ label: "Cut" }, { label: "Copy" }] },
804
+ ]}
805
+ />`}
806
+ filename="MenubarExample.tsx"
807
+ docs={<ComponentDocs rows={[
808
+ { name: "items", type: "MenubarItem[]", description: "Menu items with label and optional sub-items." },
809
+ ]} />}
810
+ >
811
+ <Menubar
812
+ items={[
813
+ {
814
+ label: "File",
815
+ items: [
816
+ { label: "New File", onClick: () => alert("New") },
817
+ { label: "Open...", onClick: () => alert("Open") },
818
+ { separator: true },
819
+ { label: "Save", onClick: () => alert("Save") },
820
+ ],
821
+ },
822
+ {
823
+ label: "Edit",
824
+ items: [
825
+ { label: "Undo", onClick: () => alert("Undo") },
826
+ { label: "Redo", onClick: () => alert("Redo") },
827
+ ],
828
+ },
829
+ { label: "View", items: [{ label: "Toggle Sidebar" }] },
830
+ ]}
831
+ />
832
+ </ShowcaseWrapper>
833
+
834
+ <ShowcaseWrapper
835
+ title="Alert Dialog"
836
+ description="Alert role confirmation dialog."
837
+ code={`import { AlertDialog, Button } from "@xenide-io/the-old-ui-theme";
838
+
839
+ <AlertDialog
840
+ title="Delete item"
841
+ confirmText="Delete"
842
+ confirmProps={{ variant: "danger" }}
843
+ onConfirm={() => {}}
844
+ >
845
+ <p>This action cannot be undone.</p>
846
+ </AlertDialog>`}
847
+ filename="AlertDialogExample.tsx"
848
+ docs={<ComponentDocs rows={[
849
+ { name: "title", type: "string" },
850
+ { name: "onConfirm", type: "() => void | Promise<void>" },
851
+ { name: "confirmText", type: "string", defaultValue: "Confirm" },
852
+ { name: "cancelText", type: "string", defaultValue: "Cancel" },
853
+ ]} />}
854
+ >
855
+ <div>
856
+ <Button variant="danger" onClick={() => setDialogOpen(true)}>Delete item</Button>
857
+ <AlertDialog
858
+ title="Delete item"
859
+ isOpen={dialogOpen}
860
+ onClose={() => setDialogOpen(false)}
861
+ onConfirm={() => alert("Deleted!")}
862
+ confirmText="Delete"
863
+ confirmProps={{ variant: "danger" }}
864
+ >
865
+ <p className="text-sm text-ph-subtle">This action cannot be undone. Are you sure you want to delete this item?</p>
866
+ </AlertDialog>
867
+ </div>
868
+ </ShowcaseWrapper>
869
+
870
+ <ShowcaseWrapper
871
+ title="Dot"
872
+ description="Tiny presence and status indicator dot."
873
+ code={`import { Dot } from "@xenide-io/the-old-ui-theme";
874
+
875
+ <Dot color="green" />
876
+ <Dot color="yellow" />
877
+ <Dot color="red" />`}
878
+ filename="DotExample.tsx"
879
+ docs={<ComponentDocs rows={[
880
+ { name: "color", type: "'green' | 'yellow' | 'red' | 'blue' | 'gray'", defaultValue: "gray" },
881
+ { name: "size", type: "'sm' | 'md'", defaultValue: "md" },
882
+ ]} />}
883
+ >
884
+ <div className="flex flex-wrap items-center gap-4">
885
+ {(["green", "yellow", "red", "blue", "gray"] as const).map((c) => (
886
+ <div key={c} className="flex items-center gap-2 text-sm text-ph-subtle">
887
+ <Dot color={c} />
888
+ <span className="capitalize">{c}</span>
889
+ </div>
890
+ ))}
891
+ </div>
892
+ </ShowcaseWrapper>
893
+
894
+ <ShowcaseWrapper
895
+ title="Collapsible"
896
+ description="Single-section disclosure with chevron toggle."
897
+ code={`import { Collapsible } from "@xenide-io/the-old-ui-theme";
898
+
899
+ <Collapsible trigger={<span>Section title</span>}>
900
+ Hidden content here
901
+ </Collapsible>`}
902
+ filename="CollapsibleExample.tsx"
903
+ docs={<ComponentDocs rows={[
904
+ { name: "trigger", type: "ReactNode", description: "Visible trigger content." },
905
+ { name: "open", type: "boolean", description: "Controlled open state." },
906
+ { name: "onOpenChange", type: "(open) => void" },
907
+ ]} />}
908
+ >
909
+ <div className="space-y-2">
910
+ <Collapsible trigger={<span className="text-sm font-medium">Configuration</span>}>
911
+ <div className="space-y-2">
912
+ <Checkbox label="Enable analytics" />
913
+ <Checkbox label="Enable session recording" />
914
+ </div>
915
+ </Collapsible>
916
+ <Collapsible trigger={<span className="text-sm font-medium">Advanced</span>}>
917
+ <p className="text-ph-subtle">Advanced configuration options go here.</p>
918
+ </Collapsible>
919
+ </div>
920
+ </ShowcaseWrapper>
921
+
922
+ <ShowcaseWrapper
923
+ title="Metric"
924
+ description="Composable stat tile with label, value, badge, and trend."
925
+ code={`import { Metric, Badge } from "@xenide-io/the-old-ui-theme";
926
+
927
+ <Metric
928
+ value="1,234"
929
+ label="Active Users"
930
+ badge={<Badge variant="success">+12%</Badge>}
931
+ />`}
932
+ filename="MetricExample.tsx"
933
+ docs={<ComponentDocs rows={[
934
+ { name: "value", type: "string | number", description: "Primary metric value." },
935
+ { name: "label", type: "string", description: "Metric label." },
936
+ { name: "badge", type: "ReactNode", description: "Optional badge/chip." },
937
+ { name: "trend", type: "ReactNode", description: "Trend indicator." },
938
+ { name: "icon", type: "ReactNode", description: "Leading icon." },
939
+ ]} />}
940
+ >
941
+ <div className="grid gap-4 sm:grid-cols-3">
942
+ <Metric
943
+ value="89.2k"
944
+ label="Page Views"
945
+ badge={<Badge variant="success">+12%</Badge>}
946
+ trend={<span>vs 79.6k last week</span>}
947
+ />
948
+ <Metric
949
+ value="2,847"
950
+ label="Active Users"
951
+ badge={<Badge variant="warning">+3%</Badge>}
952
+ trend={<span>vs 2,764 last week</span>}
953
+ />
954
+ <Metric
955
+ value="23"
956
+ label="Avg. Session (min)"
957
+ badge={<Badge variant="danger">-5%</Badge>}
958
+ trend={<span>vs 24.2 last week</span>}
959
+ />
960
+ </div>
961
+ </ShowcaseWrapper>
962
+
963
+ <ShowcaseWrapper
964
+ title="Chip"
965
+ description="Removable token for filters, tags, and multi-select values."
966
+ code={`import { Chip } from "@xenide-io/the-old-ui-theme";
967
+
968
+ <Chip onRemove={() => {}}>React</Chip>
969
+ <Chip selected>Vue</Chip>`}
970
+ filename="ChipExample.tsx"
971
+ docs={<ComponentDocs rows={[
972
+ { name: "selected", type: "boolean", defaultValue: "false" },
973
+ { name: "onRemove", type: "() => void", description: "Shows remove button." },
974
+ ]} />}
975
+ >
976
+ <div className="flex flex-wrap gap-2">
977
+ <Chip>React</Chip>
978
+ <Chip selected>Vue</Chip>
979
+ <Chip>Svelte</Chip>
980
+ <Chip selected onRemove={() => {}}>Angular</Chip>
981
+ <Chip onRemove={() => {}}>Solid</Chip>
982
+ </div>
983
+ </ShowcaseWrapper>
984
+
985
+ <ShowcaseWrapper
986
+ title="Data Table"
987
+ description="Sortable, paginated, searchable data table."
988
+ code={`import { DataTable } from "@xenide-io/the-old-ui-theme";
989
+
990
+ <DataTable
991
+ columns={[
992
+ { key: "name", label: "Name", sortable: true },
993
+ { key: "status", label: "Status" },
994
+ ]}
995
+ data={[
996
+ { name: "Item 1", status: "Active" },
997
+ ]}
998
+ searchable
999
+ pageSize={5}
1000
+ />`}
1001
+ filename="DataTableExample.tsx"
1002
+ docs={<ComponentDocs rows={[
1003
+ { name: "columns", type: "DataTableColumn[]", description: "Column definitions with key, label, render, sortable." },
1004
+ { name: "data", type: "T[]", description: "Array of data objects." },
1005
+ { name: "pageSize", type: "number", defaultValue: "10" },
1006
+ { name: "searchable", type: "boolean", defaultValue: "false" },
1007
+ ]} />}
1008
+ >
1009
+ <DataTable
1010
+ columns={[
1011
+ { key: "name", label: "Name", sortable: true },
1012
+ { key: "email", label: "Email", sortable: true },
1013
+ { key: "role", label: "Role", sortable: true },
1014
+ { key: "status", label: "Status" },
1015
+ ]}
1016
+ data={[
1017
+ { name: "Alice Johnson", email: "alice@example.com", role: "Admin", status: "Active" },
1018
+ { name: "Bob Smith", email: "bob@example.com", role: "Editor", status: "Active" },
1019
+ { name: "Charlie Lee", email: "charlie@example.com", role: "Viewer", status: "Inactive" },
1020
+ { name: "Diana Ross", email: "diana@example.com", role: "Admin", status: "Active" },
1021
+ { name: "Eve Wilson", email: "eve@example.com", role: "Editor", status: "Active" },
1022
+ { name: "Frank Brown", email: "frank@example.com", role: "Viewer", status: "Inactive" },
1023
+ { name: "Grace Chen", email: "grace@example.com", role: "Admin", status: "Active" },
1024
+ ]}
1025
+ searchable
1026
+ pageSize={3}
1027
+ />
1028
+ </ShowcaseWrapper>
1029
+
1030
+ <ShowcaseWrapper
1031
+ title="Date Picker"
1032
+ description="Calendar date picker dropdown."
1033
+ code={`import { DatePicker } from "@xenide-io/the-old-ui-theme";
1034
+
1035
+ <DatePicker
1036
+ value={new Date()}
1037
+ onChange={(date) => console.log(date)}
1038
+ />`}
1039
+ filename="DatePickerExample.tsx"
1040
+ docs={<ComponentDocs rows={[
1041
+ { name: "value", type: "Date", description: "Selected date." },
1042
+ { name: "onChange", type: "(date: Date) => void", description: "Date selection handler." },
1043
+ ]} />}
1044
+ >
1045
+ <DatePicker
1046
+ value={new Date()}
1047
+ onChange={(date) => console.log(date.toDateString())}
1048
+ />
1049
+ </ShowcaseWrapper>
1050
+ </>
1051
+ );
1052
+ }