@xenide-io/the-old-ui-theme 0.2.6 → 0.2.9
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/dist/chunk-SHF57J7U.mjs +2910 -0
- package/dist/index-CmS6hcUk.d.mts +753 -0
- package/dist/index-CmS6hcUk.d.ts +753 -0
- package/dist/index.d.mts +5 -755
- package/dist/index.d.ts +5 -755
- package/dist/index.js +43 -23
- package/dist/index.mjs +252 -2846
- package/dist/ui.d.mts +3 -0
- package/dist/ui.d.ts +3 -0
- package/dist/ui.js +2946 -0
- package/dist/ui.mjs +139 -0
- package/package.json +11 -3
- package/src/components/charts/index.ts +8 -0
- package/src/components/charts/ph-insight-charts.tsx +162 -0
- package/src/components/dashboard/DashboardFiltersBar.tsx +19 -0
- package/src/components/dashboard/DashboardGrid.tsx +23 -0
- package/src/components/dashboard/DashboardInsightPlaceholder.tsx +37 -0
- package/src/components/dashboard/DashboardKpiCard.tsx +25 -0
- package/src/components/dashboard/DashboardToolbar.tsx +23 -0
- package/src/components/dashboard/DashboardWell.tsx +10 -0
- package/src/components/dashboard/InsightMiniCard.tsx +26 -0
- package/src/components/dashboard/InsightShell.tsx +37 -0
- package/src/components/dashboard/InsightShellHeader.tsx +22 -0
- package/src/components/dashboard/MiniTrendBars.tsx +51 -0
- package/src/components/dashboard/index.ts +31 -0
- package/src/components/dashboard/types.ts +9 -0
- package/src/components/icons/IconBase.tsx +39 -0
- package/src/components/icons/createIconBase.tsx +27 -0
- package/src/components/icons/icons.tsx +367 -0
- package/src/components/icons/index.ts +3 -0
- package/src/components/sections/AccordionShowcase.tsx +45 -0
- package/src/components/sections/AlertShowcase.tsx +39 -0
- package/src/components/sections/AvatarShowcase.tsx +80 -0
- package/src/components/sections/BadgeShowcase.tsx +65 -0
- package/src/components/sections/ButtonShowcase.tsx +312 -0
- package/src/components/sections/CalendarShowcase.tsx +35 -0
- package/src/components/sections/CardShowcase.tsx +143 -0
- package/src/components/sections/ChartShowcase.tsx +190 -0
- package/src/components/sections/CodeMockupShowcase.tsx +56 -0
- package/src/components/sections/ColorPalette.tsx +117 -0
- package/src/components/sections/CommandPaletteShowcase.tsx +48 -0
- package/src/components/sections/CountdownShowcase.tsx +43 -0
- package/src/components/sections/DashboardShowcase.tsx +191 -0
- package/src/components/sections/DiffShowcase.tsx +70 -0
- package/src/components/sections/DrawerShowcase.tsx +97 -0
- package/src/components/sections/DropdownShowcase.tsx +100 -0
- package/src/components/sections/EmptyStateShowcase.tsx +50 -0
- package/src/components/sections/FilterChipsShowcase.tsx +50 -0
- package/src/components/sections/FormShowcase.tsx +126 -0
- package/src/components/sections/HoverCardShowcase.tsx +50 -0
- package/src/components/sections/IconShowcase.tsx +247 -0
- package/src/components/sections/IndicatorShowcase.tsx +52 -0
- package/src/components/sections/KbdShowcase.tsx +31 -0
- package/src/components/sections/ModalShowcase.tsx +210 -0
- package/src/components/sections/NavigationShowcase.tsx +199 -0
- package/src/components/sections/ProgressShowcase.tsx +85 -0
- package/src/components/sections/SegmentedControlShowcase.tsx +49 -0
- package/src/components/sections/SetupThemeShowcase.tsx +262 -0
- package/src/components/sections/StackShowcase.tsx +33 -0
- package/src/components/sections/StatShowcase.tsx +129 -0
- package/src/components/sections/StepperShowcase.tsx +37 -0
- package/src/components/sections/SwapShowcase.tsx +91 -0
- package/src/components/sections/TabShowcase.tsx +84 -0
- package/src/components/sections/TableShowcase.tsx +140 -0
- package/src/components/sections/TimelineShowcase.tsx +83 -0
- package/src/components/sections/ToastShowcase.tsx +108 -0
- package/src/components/sections/TooltipShowcase.tsx +44 -0
- package/src/components/sections/UtilityShowcase.tsx +81 -0
- package/src/components/ui/Accordion.tsx +77 -0
- package/src/components/ui/Alert.tsx +68 -0
- package/src/components/ui/Avatar.tsx +97 -0
- package/src/components/ui/Badge.tsx +55 -0
- package/src/components/ui/Button.tsx +110 -0
- package/src/components/ui/ButtonChrome.tsx +20 -0
- package/src/components/ui/Calendar.tsx +116 -0
- package/src/components/ui/Card.tsx +60 -0
- package/src/components/ui/ChatBubble.tsx +71 -0
- package/src/components/ui/CodeBlock.tsx +48 -0
- package/src/components/ui/CollapsibleSection.tsx +49 -0
- package/src/components/ui/CommandPalette.tsx +137 -0
- package/src/components/ui/ComponentDocs.tsx +52 -0
- package/src/components/ui/Drawer.tsx +71 -0
- package/src/components/ui/DropdownMenu.tsx +138 -0
- package/src/components/ui/EmptyState.tsx +33 -0
- package/src/components/ui/FilterChips.tsx +50 -0
- package/src/components/ui/HoverCard.tsx +36 -0
- package/src/components/ui/Indicator.tsx +61 -0
- package/src/components/ui/Input.tsx +359 -0
- package/src/components/ui/Kbd.tsx +38 -0
- package/src/components/ui/Modal.tsx +75 -0
- package/src/components/ui/Navigation.tsx +94 -0
- package/src/components/ui/Panel.tsx +18 -0
- package/src/components/ui/Progress.tsx +59 -0
- package/src/components/ui/Rating.tsx +65 -0
- package/src/components/ui/SearchInput.tsx +106 -0
- package/src/components/ui/SegmentedControl.tsx +44 -0
- package/src/components/ui/ShowcaseWrapper.tsx +136 -0
- package/src/components/ui/Stat.tsx +39 -0
- package/src/components/ui/Stepper.tsx +75 -0
- package/src/components/ui/Table.tsx +55 -0
- package/src/components/ui/Tabs.tsx +53 -0
- package/src/components/ui/Terminal.tsx +54 -0
- package/src/components/ui/ThemeDomSync.tsx +17 -0
- package/src/components/ui/ThemeManager.tsx +18 -0
- package/src/components/ui/ThemeSwitcher.tsx +46 -0
- package/src/components/ui/Timeline.tsx +60 -0
- package/src/components/ui/Toast.tsx +70 -0
- package/src/components/ui/Typography.tsx +129 -0
- package/src/components/ui/index.ts +92 -0
- package/src/styles/themes.css +118 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { ShowcaseWrapper } from "@/components/ui";
|
|
5
|
+
|
|
6
|
+
/** Lightweight before/after — PostHog product diffs screenshots in Visual Review Playwright suites. */
|
|
7
|
+
|
|
8
|
+
export default function DiffShowcase() {
|
|
9
|
+
const [pct, setPct] = useState(50);
|
|
10
|
+
|
|
11
|
+
const code = `
|
|
12
|
+
|
|
13
|
+
<div className="ph-panel max-w-3xl">
|
|
14
|
+
<label className="mb-6 flex items-center gap-4 text-xs font-semibold uppercase tracking-wider text-ph-mutedtext">
|
|
15
|
+
Position
|
|
16
|
+
<input type="range" min={0} max={100} value={pct} onChange={(e) => setPct(Number(e.target.value))} className="flex-1" />
|
|
17
|
+
<span className="tabular-nums text-ph-ink">{pct}%</span>
|
|
18
|
+
</label>
|
|
19
|
+
<div className="relative aspect-video overflow-hidden rounded-xl border border-ph-border shadow-ph-md">
|
|
20
|
+
<div className="absolute inset-0 grid place-content-center bg-ph-toolbar text-xs font-semibold uppercase text-ph-mutedtext">
|
|
21
|
+
After · lightened neutral surfaces
|
|
22
|
+
</div>
|
|
23
|
+
<div
|
|
24
|
+
className="absolute inset-y-0 left-0 overflow-hidden bg-ph-muted"
|
|
25
|
+
style={{
|
|
26
|
+
clipPath: \`inset(0 \${100 - pct}% 0 0)\`,
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
<div className="grid h-full place-content-center text-xs font-semibold uppercase text-ph-ink">
|
|
30
|
+
Before · richer contrast rails
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<span
|
|
34
|
+
className="pointer-events-none absolute inset-y-0 w-px bg-ph-surface"
|
|
35
|
+
style={{ left: \`\${pct}%\`, boxShadow: "0 0 0 1px hsl(0deg 0% 0% / .15)" }}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</div>`;
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ShowcaseWrapper title="Diff slider" code={code} filename="DiffExample.tsx">
|
|
42
|
+
<div className="ph-panel max-w-3xl">
|
|
43
|
+
<label className="mb-6 flex items-center gap-4 text-xs font-semibold uppercase tracking-wider text-ph-mutedtext">
|
|
44
|
+
Position
|
|
45
|
+
<input type="range" min={0} max={100} value={pct} onChange={(e) => setPct(Number(e.target.value))} className="flex-1" />
|
|
46
|
+
<span className="tabular-nums text-ph-ink">{pct}%</span>
|
|
47
|
+
</label>
|
|
48
|
+
<div className="relative aspect-video overflow-hidden rounded-xl border border-ph-border shadow-ph-md">
|
|
49
|
+
<div className="absolute inset-0 grid place-content-center bg-ph-toolbar text-xs font-semibold uppercase text-ph-mutedtext">
|
|
50
|
+
After · lightened neutral surfaces
|
|
51
|
+
</div>
|
|
52
|
+
<div
|
|
53
|
+
className="absolute inset-y-0 left-0 overflow-hidden bg-ph-muted"
|
|
54
|
+
style={{
|
|
55
|
+
clipPath: `inset(0 ${100 - pct}% 0 0)`,
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
<div className="grid h-full place-content-center text-xs font-semibold uppercase text-ph-ink">
|
|
59
|
+
Before · richer contrast rails
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<span
|
|
63
|
+
className="pointer-events-none absolute inset-y-0 w-px bg-ph-surface"
|
|
64
|
+
style={{ left: `${pct}%`, boxShadow: "0 0 0 1px hsl(0deg 0% 0% / .15)" }}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</ShowcaseWrapper>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import {
|
|
5
|
+
IconCohort,
|
|
6
|
+
IconCumulativeChart,
|
|
7
|
+
IconFlag,
|
|
8
|
+
IconFlask,
|
|
9
|
+
IconHome,
|
|
10
|
+
IconPanelRight,
|
|
11
|
+
IconTuning,
|
|
12
|
+
} from "@/components/icons";
|
|
13
|
+
import { Button, ComponentDocs, Drawer, ShowcaseWrapper } from "@/components/ui";
|
|
14
|
+
|
|
15
|
+
const navItems = [
|
|
16
|
+
{ icon: IconHome, label: "Dashboard" },
|
|
17
|
+
{ icon: IconCumulativeChart, label: "Insights" },
|
|
18
|
+
{ icon: IconCohort, label: "Persons" },
|
|
19
|
+
{ icon: IconFlag, label: "Feature flags" },
|
|
20
|
+
{ icon: IconFlask, label: "Experiments" },
|
|
21
|
+
{ icon: IconTuning, label: "Settings" },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export default function DrawerShowcase() {
|
|
25
|
+
const [open, setOpen] = useState(false);
|
|
26
|
+
|
|
27
|
+
const code = `import { IconCohort, IconCumulativeChart, IconFlag, IconFlask, IconHome, IconPanelRight, IconTuning } from "the-old-ui";
|
|
28
|
+
import { Button, Drawer } from "the-old-ui";
|
|
29
|
+
|
|
30
|
+
<div className="ph-panel">
|
|
31
|
+
<Button
|
|
32
|
+
variant="primary"
|
|
33
|
+
icon={<IconPanelRight className="h-4 w-4" aria-hidden />}
|
|
34
|
+
onClick={() => setOpen(true)}
|
|
35
|
+
>
|
|
36
|
+
Inspect graph
|
|
37
|
+
</Button>
|
|
38
|
+
|
|
39
|
+
<Drawer open={open} onClose={() => setOpen(false)} title="Insight controls">
|
|
40
|
+
<nav className="flex flex-col gap-1 px-3 py-4">
|
|
41
|
+
{navItems.map((item) => {
|
|
42
|
+
const Icon = item.icon;
|
|
43
|
+
return (
|
|
44
|
+
<button key={item.label} type="button" className="flex items-center gap-3 rounded-lg px-3 py-2 text-left text-sm font-medium text-ph-subtle transition hover:bg-ph-muted">
|
|
45
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
46
|
+
{item.label}
|
|
47
|
+
</button>
|
|
48
|
+
);
|
|
49
|
+
})}
|
|
50
|
+
</nav>
|
|
51
|
+
</Drawer>
|
|
52
|
+
</div>`;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<ShowcaseWrapper
|
|
56
|
+
title="Drawers"
|
|
57
|
+
description="Slide-out panels with overlay backdrop — useful for secondary navigation, detail views, or configuration panels."
|
|
58
|
+
code={code}
|
|
59
|
+
filename="DrawerExample.tsx"
|
|
60
|
+
docs={
|
|
61
|
+
<ComponentDocs
|
|
62
|
+
rows={[
|
|
63
|
+
{ name: "open", type: "boolean", defaultValue: "false", description: "Controls drawer visibility." },
|
|
64
|
+
{ name: "onClose", type: "() => void", description: "Called by backdrop and close button." },
|
|
65
|
+
{ name: "side", type: "left | right", defaultValue: "right", description: "Which side the drawer enters from." },
|
|
66
|
+
{ name: "size", type: "sm | md | lg", defaultValue: "md", description: "Controls drawer width." },
|
|
67
|
+
{ name: "title", type: "ReactNode", description: "Optional header title." },
|
|
68
|
+
]}
|
|
69
|
+
/>
|
|
70
|
+
}
|
|
71
|
+
>
|
|
72
|
+
<div className="ph-panel">
|
|
73
|
+
<Button
|
|
74
|
+
variant="primary"
|
|
75
|
+
icon={<IconPanelRight className="h-4 w-4" aria-hidden />}
|
|
76
|
+
onClick={() => setOpen(true)}
|
|
77
|
+
>
|
|
78
|
+
Inspect graph
|
|
79
|
+
</Button>
|
|
80
|
+
|
|
81
|
+
<Drawer open={open} onClose={() => setOpen(false)} title="Insight controls">
|
|
82
|
+
<nav className="flex flex-col gap-1 px-3 py-4">
|
|
83
|
+
{navItems.map((item) => {
|
|
84
|
+
const Icon = item.icon;
|
|
85
|
+
return (
|
|
86
|
+
<button key={item.label} type="button" className="flex items-center gap-3 rounded-lg px-3 py-2 text-left text-sm font-medium text-ph-subtle transition hover:bg-ph-muted">
|
|
87
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
88
|
+
{item.label}
|
|
89
|
+
</button>
|
|
90
|
+
);
|
|
91
|
+
})}
|
|
92
|
+
</nav>
|
|
93
|
+
</Drawer>
|
|
94
|
+
</div>
|
|
95
|
+
</ShowcaseWrapper>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { IconCopy, IconEdit, IconLogout, IconPerson, IconTrash, IconTuning } from "@/components/icons";
|
|
4
|
+
import { DropdownButton, DropdownItem, ShowcaseWrapper } from "@/components/ui";
|
|
5
|
+
|
|
6
|
+
export default function DropdownShowcase() {
|
|
7
|
+
const code = `import { IconCopy, IconEdit, IconLogout, IconPerson, IconTrash, IconTuning } from "the-old-ui";
|
|
8
|
+
import { DropdownButton, DropdownItem } from "the-old-ui";
|
|
9
|
+
|
|
10
|
+
<div className="ph-panel space-y-6">
|
|
11
|
+
<p className="text-sm text-ph-subtle">
|
|
12
|
+
Use <code className="ph-kbd">DropdownButton</code> from{" "}
|
|
13
|
+
<code className="ph-kbd">the-old-ui</code> — labelled Lemon triggers +{" "}
|
|
14
|
+
<code className="ph-kbd">DropdownItem</code> menu rows.
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<div className="flex flex-wrap items-start gap-6">
|
|
18
|
+
<DropdownButton label="Actions" variant="primary">
|
|
19
|
+
<DropdownItem>Refresh cache</DropdownItem>
|
|
20
|
+
<DropdownItem>Export HogQL</DropdownItem>
|
|
21
|
+
<DropdownItem>Jump to inspector</DropdownItem>
|
|
22
|
+
</DropdownButton>
|
|
23
|
+
|
|
24
|
+
<DropdownButton label="Account" variant="secondary">
|
|
25
|
+
<DropdownItem>
|
|
26
|
+
<IconPerson className="h-4 w-4" aria-hidden /> Profile
|
|
27
|
+
</DropdownItem>
|
|
28
|
+
<DropdownItem>
|
|
29
|
+
<IconTuning className="h-4 w-4" aria-hidden /> Project settings
|
|
30
|
+
</DropdownItem>
|
|
31
|
+
<DropdownItem>
|
|
32
|
+
<IconLogout className="h-4 w-4" aria-hidden /> Sign out
|
|
33
|
+
</DropdownItem>
|
|
34
|
+
</DropdownButton>
|
|
35
|
+
|
|
36
|
+
<DropdownButton label="Row menu" variant="accent" outline>
|
|
37
|
+
<DropdownItem>
|
|
38
|
+
<IconEdit className="h-4 w-4" aria-hidden /> Rename
|
|
39
|
+
</DropdownItem>
|
|
40
|
+
<DropdownItem>
|
|
41
|
+
<IconCopy className="h-4 w-4" aria-hidden /> Duplicate key
|
|
42
|
+
</DropdownItem>
|
|
43
|
+
<div className="my-1 h-px bg-ph-border" />
|
|
44
|
+
<DropdownItem className="text-ph-danger">
|
|
45
|
+
<IconTrash className="h-4 w-4" aria-hidden /> Delete
|
|
46
|
+
</DropdownItem>
|
|
47
|
+
</DropdownButton>
|
|
48
|
+
</div>
|
|
49
|
+
</div>`;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<ShowcaseWrapper
|
|
53
|
+
title="Dropdowns"
|
|
54
|
+
description="Use DropdownButton from the-old-ui — labelled Lemon triggers + DropdownItem menu rows."
|
|
55
|
+
code={code}
|
|
56
|
+
filename="DropdownExample.tsx"
|
|
57
|
+
>
|
|
58
|
+
<div className="ph-panel space-y-6">
|
|
59
|
+
<p className="text-sm text-ph-subtle">
|
|
60
|
+
Use <code className="ph-kbd">DropdownButton</code> from{" "}
|
|
61
|
+
<code className="ph-kbd">the-old-ui</code> — labelled Lemon triggers +{" "}
|
|
62
|
+
<code className="ph-kbd">DropdownItem</code> menu rows.
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<div className="flex flex-wrap items-start gap-6">
|
|
66
|
+
<DropdownButton label="Actions" variant="primary">
|
|
67
|
+
<DropdownItem>Refresh cache</DropdownItem>
|
|
68
|
+
<DropdownItem>Export HogQL</DropdownItem>
|
|
69
|
+
<DropdownItem>Jump to inspector</DropdownItem>
|
|
70
|
+
</DropdownButton>
|
|
71
|
+
|
|
72
|
+
<DropdownButton label="Account" variant="secondary">
|
|
73
|
+
<DropdownItem>
|
|
74
|
+
<IconPerson className="h-4 w-4" aria-hidden /> Profile
|
|
75
|
+
</DropdownItem>
|
|
76
|
+
<DropdownItem>
|
|
77
|
+
<IconTuning className="h-4 w-4" aria-hidden /> Project settings
|
|
78
|
+
</DropdownItem>
|
|
79
|
+
<DropdownItem>
|
|
80
|
+
<IconLogout className="h-4 w-4" aria-hidden /> Sign out
|
|
81
|
+
</DropdownItem>
|
|
82
|
+
</DropdownButton>
|
|
83
|
+
|
|
84
|
+
<DropdownButton label="Row menu" variant="accent" outline>
|
|
85
|
+
<DropdownItem>
|
|
86
|
+
<IconEdit className="h-4 w-4" aria-hidden /> Rename
|
|
87
|
+
</DropdownItem>
|
|
88
|
+
<DropdownItem>
|
|
89
|
+
<IconCopy className="h-4 w-4" aria-hidden /> Duplicate key
|
|
90
|
+
</DropdownItem>
|
|
91
|
+
<div className="my-1 h-px bg-ph-border" />
|
|
92
|
+
<DropdownItem className="text-ph-danger">
|
|
93
|
+
<IconTrash className="h-4 w-4" aria-hidden /> Delete
|
|
94
|
+
</DropdownItem>
|
|
95
|
+
</DropdownButton>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</ShowcaseWrapper>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Button, ComponentDocs, EmptyState, ShowcaseWrapper } from "@/components/ui";
|
|
4
|
+
import { IconBox, IconPlus } from "@/components/icons";
|
|
5
|
+
|
|
6
|
+
export default function EmptyStateShowcase() {
|
|
7
|
+
const code = `import { Button, EmptyState } from "the-old-ui";
|
|
8
|
+
import { IconBox, IconPlus } from "the-old-ui";
|
|
9
|
+
|
|
10
|
+
<EmptyState
|
|
11
|
+
icon={<IconBox className="h-7 w-7" />}
|
|
12
|
+
title="No projects yet"
|
|
13
|
+
description="Get started by creating your first project to organize your analytics."
|
|
14
|
+
action={
|
|
15
|
+
<Button icon={<IconPlus className="h-4 w-4" />}>
|
|
16
|
+
Create Project
|
|
17
|
+
</Button>
|
|
18
|
+
}
|
|
19
|
+
/>`;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<ShowcaseWrapper
|
|
23
|
+
title="Empty State"
|
|
24
|
+
description="Reusable blank-state component for zero data, filtered results, or onboarding prompts."
|
|
25
|
+
code={code}
|
|
26
|
+
filename="EmptyStateExample.tsx"
|
|
27
|
+
docs={
|
|
28
|
+
<ComponentDocs
|
|
29
|
+
rows={[
|
|
30
|
+
{ name: "icon", type: "ReactNode", description: "Optional visual icon." },
|
|
31
|
+
{ name: "title", type: "string", description: "Primary message." },
|
|
32
|
+
{ name: "description", type: "string", description: "Supporting copy." },
|
|
33
|
+
{ name: "action", type: "ReactNode", description: "Primary CTA slot." },
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
}
|
|
37
|
+
>
|
|
38
|
+
<EmptyState
|
|
39
|
+
icon={<IconBox className="h-7 w-7" />}
|
|
40
|
+
title="No projects yet"
|
|
41
|
+
description="Get started by creating your first project to organize your analytics."
|
|
42
|
+
action={
|
|
43
|
+
<Button icon={<IconPlus className="h-4 w-4" />}>
|
|
44
|
+
Create Project
|
|
45
|
+
</Button>
|
|
46
|
+
}
|
|
47
|
+
/>
|
|
48
|
+
</ShowcaseWrapper>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { ComponentDocs, FilterChips, ShowcaseWrapper } from "@/components/ui";
|
|
5
|
+
|
|
6
|
+
export default function FilterChipsShowcase() {
|
|
7
|
+
const [chips, setChips] = useState([
|
|
8
|
+
{ id: "1", label: "Active", active: true },
|
|
9
|
+
{ id: "2", label: "Archived", active: false },
|
|
10
|
+
{ id: "3", label: "Draft", active: false },
|
|
11
|
+
{ id: "4", label: "Pending", active: true },
|
|
12
|
+
{ id: "5", label: "Failed", active: false },
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const toggleChip = (id: string) => {
|
|
16
|
+
setChips((prev) => prev.map((chip) => (chip.id === id ? { ...chip, active: !chip.active } : chip)));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const removeChip = (id: string) => {
|
|
20
|
+
setChips((prev) => prev.filter((chip) => chip.id !== id));
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const code = `import { FilterChips } from "the-old-ui";
|
|
24
|
+
|
|
25
|
+
<div className="ph-panel">
|
|
26
|
+
<FilterChips chips={chips} onToggle={toggleChip} onRemove={removeChip} />
|
|
27
|
+
</div>`;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<ShowcaseWrapper
|
|
31
|
+
title="Filter Chips"
|
|
32
|
+
description="Controlled chips for active filters, facets, and quick toggles."
|
|
33
|
+
code={code}
|
|
34
|
+
filename="FilterChipsExample.tsx"
|
|
35
|
+
docs={
|
|
36
|
+
<ComponentDocs
|
|
37
|
+
rows={[
|
|
38
|
+
{ name: "chips", type: "{ id; label; active }[]", description: "Chips to render." },
|
|
39
|
+
{ name: "onToggle", type: "(id: string) => void", description: "Called when a chip is clicked." },
|
|
40
|
+
{ name: "onRemove", type: "(id: string) => void", description: "Shows remove control when provided." },
|
|
41
|
+
]}
|
|
42
|
+
/>
|
|
43
|
+
}
|
|
44
|
+
>
|
|
45
|
+
<div className="ph-panel">
|
|
46
|
+
<FilterChips chips={chips} onToggle={toggleChip} onRemove={removeChip} />
|
|
47
|
+
</div>
|
|
48
|
+
</ShowcaseWrapper>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComponentDocs,
|
|
3
|
+
Checkbox,
|
|
4
|
+
FileUpload,
|
|
5
|
+
Input,
|
|
6
|
+
Panel,
|
|
7
|
+
Radio,
|
|
8
|
+
Range,
|
|
9
|
+
Rating,
|
|
10
|
+
SearchGroup,
|
|
11
|
+
Select,
|
|
12
|
+
Textarea,
|
|
13
|
+
Toggle,
|
|
14
|
+
ShowcaseWrapper,
|
|
15
|
+
} from "@/components/ui";
|
|
16
|
+
|
|
17
|
+
export default function FormShowcase() {
|
|
18
|
+
const code = `import { Checkbox, FileUpload, Input, Panel, Radio, Range, Rating, SearchGroup, Select, Textarea, Toggle } from "the-old-ui";
|
|
19
|
+
|
|
20
|
+
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
|
|
21
|
+
<Panel title="Text inputs" className="space-y-6">
|
|
22
|
+
<Input label="Default" placeholder="Filter events..." />
|
|
23
|
+
<Input label="Error" placeholder="hogql query" error="Malformed identifier near line 12" />
|
|
24
|
+
<Input label="Ghost toolbar field" type="search" placeholder="Search..." variant="ghost" />
|
|
25
|
+
<Input label="Disabled" placeholder="Unavailable" disabled />
|
|
26
|
+
</Panel>
|
|
27
|
+
|
|
28
|
+
<Panel title="Select & textarea" className="space-y-6">
|
|
29
|
+
<Select label="Environment" defaultValue="prod">
|
|
30
|
+
<option value="prod">Production</option>
|
|
31
|
+
<option value="staging">Staging</option>
|
|
32
|
+
<option value="dev">Development</option>
|
|
33
|
+
</Select>
|
|
34
|
+
|
|
35
|
+
<Textarea label="Description" placeholder="Explain the rollout..." />
|
|
36
|
+
|
|
37
|
+
<Checkbox label="Autocapture pageviews" defaultChecked />
|
|
38
|
+
<Checkbox label="Record console logs (disabled product)" disabled />
|
|
39
|
+
|
|
40
|
+
<div className="flex flex-col gap-2">
|
|
41
|
+
<Radio name="cohort" label="Dynamic cohort" defaultChecked />
|
|
42
|
+
<Radio name="cohort" label="Static upload" />
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<Toggle label="Session replay" defaultChecked />
|
|
46
|
+
<Toggle label="Error tracking (disabled)" disabled />
|
|
47
|
+
</Panel>
|
|
48
|
+
|
|
49
|
+
<Panel title="Range, rating, uploads" className="space-y-6 lg:col-span-2">
|
|
50
|
+
<Range label="Sample rate" min={0} max={100} defaultValue={42} minLabel="Off" valueLabel="42%" maxLabel="Full" wrapperClassName="max-w-xl" />
|
|
51
|
+
|
|
52
|
+
<Rating label="Satisfaction" value={4} />
|
|
53
|
+
|
|
54
|
+
<FileUpload label="Source map archive" prompt="Drop tarball or browse" wrapperClassName="max-w-xl" />
|
|
55
|
+
|
|
56
|
+
<SearchGroup label="Grouped search" submitLabel="Search records" />
|
|
57
|
+
</Panel>
|
|
58
|
+
</div>`;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ShowcaseWrapper
|
|
62
|
+
title="Inputs & Forms"
|
|
63
|
+
description="Actual exported input components with built-in labels, error states, helper text, disabled state, and size/variant props."
|
|
64
|
+
code={code}
|
|
65
|
+
filename="FormExample.tsx"
|
|
66
|
+
docs={
|
|
67
|
+
<ComponentDocs
|
|
68
|
+
title="Input components"
|
|
69
|
+
rows={[
|
|
70
|
+
{ name: "Input", type: "text | search | email | password", description: "Labelled input with error, helperText, size, and variant props." },
|
|
71
|
+
{ name: "Select", type: "select", description: "Labelled select with error, helperText, size, and disabled props." },
|
|
72
|
+
{ name: "Textarea", type: "textarea", description: "Labelled multiline input with the same state props as Input." },
|
|
73
|
+
{ name: "Checkbox", type: "checkbox", description: "Checkbox with label and native input props." },
|
|
74
|
+
{ name: "Radio", type: "radio", description: "Radio item with label and native input props." },
|
|
75
|
+
{ name: "Toggle", type: "switch", description: "Switch-style checkbox with row layout." },
|
|
76
|
+
{ name: "Range", type: "range", description: "Range slider with optional min/value/max labels." },
|
|
77
|
+
{ name: "Rating", type: "rating", description: "Star rating display/control with value, max, and onChange props." },
|
|
78
|
+
{ name: "FileUpload", type: "file", description: "Dropzone-style file input wrapper." },
|
|
79
|
+
{ name: "size", type: "sm | md | lg", defaultValue: "md", description: "Shared density prop for Input, Select, and Textarea." },
|
|
80
|
+
{ name: "variant", type: "default | ghost", defaultValue: "default", description: "Input visual variant. Ghost is useful in toolbar/search contexts." },
|
|
81
|
+
]}
|
|
82
|
+
/>
|
|
83
|
+
}
|
|
84
|
+
>
|
|
85
|
+
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
|
|
86
|
+
<Panel title="Text inputs" className="space-y-6">
|
|
87
|
+
<Input label="Default" placeholder="Filter events..." />
|
|
88
|
+
<Input label="Error" placeholder="hogql query" error="Malformed identifier near line 12" />
|
|
89
|
+
<Input label="Ghost toolbar field" type="search" placeholder="Search..." variant="ghost" />
|
|
90
|
+
<Input label="Disabled" placeholder="Unavailable" disabled />
|
|
91
|
+
</Panel>
|
|
92
|
+
|
|
93
|
+
<Panel title="Select & textarea" className="space-y-6">
|
|
94
|
+
<Select label="Environment" defaultValue="prod">
|
|
95
|
+
<option value="prod">Production</option>
|
|
96
|
+
<option value="staging">Staging</option>
|
|
97
|
+
<option value="dev">Development</option>
|
|
98
|
+
</Select>
|
|
99
|
+
|
|
100
|
+
<Textarea label="Description" placeholder="Explain the rollout..." />
|
|
101
|
+
|
|
102
|
+
<Checkbox label="Autocapture pageviews" defaultChecked />
|
|
103
|
+
<Checkbox label="Record console logs (disabled product)" disabled />
|
|
104
|
+
|
|
105
|
+
<div className="flex flex-col gap-2">
|
|
106
|
+
<Radio name="cohort" label="Dynamic cohort" defaultChecked />
|
|
107
|
+
<Radio name="cohort" label="Static upload" />
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<Toggle label="Session replay" defaultChecked />
|
|
111
|
+
<Toggle label="Error tracking (disabled)" disabled />
|
|
112
|
+
</Panel>
|
|
113
|
+
|
|
114
|
+
<Panel title="Range, rating, uploads" className="space-y-6 lg:col-span-2">
|
|
115
|
+
<Range label="Sample rate" min={0} max={100} defaultValue={42} minLabel="Off" valueLabel="42%" maxLabel="Full" wrapperClassName="max-w-xl" />
|
|
116
|
+
|
|
117
|
+
<Rating label="Satisfaction" value={4} />
|
|
118
|
+
|
|
119
|
+
<FileUpload label="Source map archive" prompt="Drop tarball or browse" wrapperClassName="max-w-xl" />
|
|
120
|
+
|
|
121
|
+
<SearchGroup label="Grouped search" submitLabel="Search records" />
|
|
122
|
+
</Panel>
|
|
123
|
+
</div>
|
|
124
|
+
</ShowcaseWrapper>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Badge, Button, ComponentDocs, HoverCard, ShowcaseWrapper } from "@/components/ui";
|
|
4
|
+
|
|
5
|
+
export default function HoverCardShowcase() {
|
|
6
|
+
const code = `import { Badge, Button, HoverCard } from "the-old-ui";
|
|
7
|
+
|
|
8
|
+
<div className="ph-panel flex justify-center py-12">
|
|
9
|
+
<HoverCard trigger={<Button>Hover me</Button>}>
|
|
10
|
+
<div className="space-y-2">
|
|
11
|
+
<h4 className="font-semibold text-ph-ink">User Profile</h4>
|
|
12
|
+
<p className="text-sm text-ph-subtle">This is a hover card with rich content that appears on hover.</p>
|
|
13
|
+
<div className="flex gap-2 pt-2">
|
|
14
|
+
<Badge variant="brand">Admin</Badge>
|
|
15
|
+
<Badge variant="neutral">Pro</Badge>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</HoverCard>
|
|
19
|
+
</div>`;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<ShowcaseWrapper
|
|
23
|
+
title="Hover Card"
|
|
24
|
+
description="Rich hover disclosure for contextual details."
|
|
25
|
+
code={code}
|
|
26
|
+
filename="HoverCardExample.tsx"
|
|
27
|
+
docs={
|
|
28
|
+
<ComponentDocs
|
|
29
|
+
rows={[
|
|
30
|
+
{ name: "trigger", type: "ReactNode", description: "Element users hover or focus." },
|
|
31
|
+
{ name: "children", type: "ReactNode", description: "Content shown in the card." },
|
|
32
|
+
]}
|
|
33
|
+
/>
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
<div className="ph-panel flex justify-center py-12">
|
|
37
|
+
<HoverCard trigger={<Button>Hover me</Button>}>
|
|
38
|
+
<div className="space-y-2">
|
|
39
|
+
<h4 className="font-semibold text-ph-ink">User Profile</h4>
|
|
40
|
+
<p className="text-sm text-ph-subtle">This is a hover card with rich content that appears on hover.</p>
|
|
41
|
+
<div className="flex gap-2 pt-2">
|
|
42
|
+
<Badge variant="brand">Admin</Badge>
|
|
43
|
+
<Badge variant="neutral">Pro</Badge>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</HoverCard>
|
|
47
|
+
</div>
|
|
48
|
+
</ShowcaseWrapper>
|
|
49
|
+
);
|
|
50
|
+
}
|