@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.
Files changed (110) hide show
  1. package/dist/chunk-SHF57J7U.mjs +2910 -0
  2. package/dist/index-CmS6hcUk.d.mts +753 -0
  3. package/dist/index-CmS6hcUk.d.ts +753 -0
  4. package/dist/index.d.mts +5 -755
  5. package/dist/index.d.ts +5 -755
  6. package/dist/index.js +43 -23
  7. package/dist/index.mjs +252 -2846
  8. package/dist/ui.d.mts +3 -0
  9. package/dist/ui.d.ts +3 -0
  10. package/dist/ui.js +2946 -0
  11. package/dist/ui.mjs +139 -0
  12. package/package.json +11 -3
  13. package/src/components/charts/index.ts +8 -0
  14. package/src/components/charts/ph-insight-charts.tsx +162 -0
  15. package/src/components/dashboard/DashboardFiltersBar.tsx +19 -0
  16. package/src/components/dashboard/DashboardGrid.tsx +23 -0
  17. package/src/components/dashboard/DashboardInsightPlaceholder.tsx +37 -0
  18. package/src/components/dashboard/DashboardKpiCard.tsx +25 -0
  19. package/src/components/dashboard/DashboardToolbar.tsx +23 -0
  20. package/src/components/dashboard/DashboardWell.tsx +10 -0
  21. package/src/components/dashboard/InsightMiniCard.tsx +26 -0
  22. package/src/components/dashboard/InsightShell.tsx +37 -0
  23. package/src/components/dashboard/InsightShellHeader.tsx +22 -0
  24. package/src/components/dashboard/MiniTrendBars.tsx +51 -0
  25. package/src/components/dashboard/index.ts +31 -0
  26. package/src/components/dashboard/types.ts +9 -0
  27. package/src/components/icons/IconBase.tsx +39 -0
  28. package/src/components/icons/createIconBase.tsx +27 -0
  29. package/src/components/icons/icons.tsx +367 -0
  30. package/src/components/icons/index.ts +3 -0
  31. package/src/components/sections/AccordionShowcase.tsx +45 -0
  32. package/src/components/sections/AlertShowcase.tsx +39 -0
  33. package/src/components/sections/AvatarShowcase.tsx +80 -0
  34. package/src/components/sections/BadgeShowcase.tsx +65 -0
  35. package/src/components/sections/ButtonShowcase.tsx +312 -0
  36. package/src/components/sections/CalendarShowcase.tsx +35 -0
  37. package/src/components/sections/CardShowcase.tsx +143 -0
  38. package/src/components/sections/ChartShowcase.tsx +190 -0
  39. package/src/components/sections/CodeMockupShowcase.tsx +56 -0
  40. package/src/components/sections/ColorPalette.tsx +117 -0
  41. package/src/components/sections/CommandPaletteShowcase.tsx +48 -0
  42. package/src/components/sections/CountdownShowcase.tsx +43 -0
  43. package/src/components/sections/DashboardShowcase.tsx +191 -0
  44. package/src/components/sections/DiffShowcase.tsx +70 -0
  45. package/src/components/sections/DrawerShowcase.tsx +97 -0
  46. package/src/components/sections/DropdownShowcase.tsx +100 -0
  47. package/src/components/sections/EmptyStateShowcase.tsx +50 -0
  48. package/src/components/sections/FilterChipsShowcase.tsx +50 -0
  49. package/src/components/sections/FormShowcase.tsx +126 -0
  50. package/src/components/sections/HoverCardShowcase.tsx +50 -0
  51. package/src/components/sections/IconShowcase.tsx +247 -0
  52. package/src/components/sections/IndicatorShowcase.tsx +52 -0
  53. package/src/components/sections/KbdShowcase.tsx +31 -0
  54. package/src/components/sections/ModalShowcase.tsx +210 -0
  55. package/src/components/sections/NavigationShowcase.tsx +199 -0
  56. package/src/components/sections/ProgressShowcase.tsx +85 -0
  57. package/src/components/sections/SegmentedControlShowcase.tsx +49 -0
  58. package/src/components/sections/SetupThemeShowcase.tsx +262 -0
  59. package/src/components/sections/StackShowcase.tsx +33 -0
  60. package/src/components/sections/StatShowcase.tsx +129 -0
  61. package/src/components/sections/StepperShowcase.tsx +37 -0
  62. package/src/components/sections/SwapShowcase.tsx +91 -0
  63. package/src/components/sections/TabShowcase.tsx +84 -0
  64. package/src/components/sections/TableShowcase.tsx +140 -0
  65. package/src/components/sections/TimelineShowcase.tsx +83 -0
  66. package/src/components/sections/ToastShowcase.tsx +108 -0
  67. package/src/components/sections/TooltipShowcase.tsx +44 -0
  68. package/src/components/sections/UtilityShowcase.tsx +81 -0
  69. package/src/components/ui/Accordion.tsx +77 -0
  70. package/src/components/ui/Alert.tsx +68 -0
  71. package/src/components/ui/Avatar.tsx +97 -0
  72. package/src/components/ui/Badge.tsx +55 -0
  73. package/src/components/ui/Button.tsx +110 -0
  74. package/src/components/ui/ButtonChrome.tsx +20 -0
  75. package/src/components/ui/Calendar.tsx +116 -0
  76. package/src/components/ui/Card.tsx +60 -0
  77. package/src/components/ui/ChatBubble.tsx +71 -0
  78. package/src/components/ui/CodeBlock.tsx +48 -0
  79. package/src/components/ui/CollapsibleSection.tsx +49 -0
  80. package/src/components/ui/CommandPalette.tsx +137 -0
  81. package/src/components/ui/ComponentDocs.tsx +52 -0
  82. package/src/components/ui/Drawer.tsx +71 -0
  83. package/src/components/ui/DropdownMenu.tsx +138 -0
  84. package/src/components/ui/EmptyState.tsx +33 -0
  85. package/src/components/ui/FilterChips.tsx +50 -0
  86. package/src/components/ui/HoverCard.tsx +36 -0
  87. package/src/components/ui/Indicator.tsx +61 -0
  88. package/src/components/ui/Input.tsx +359 -0
  89. package/src/components/ui/Kbd.tsx +38 -0
  90. package/src/components/ui/Modal.tsx +75 -0
  91. package/src/components/ui/Navigation.tsx +94 -0
  92. package/src/components/ui/Panel.tsx +18 -0
  93. package/src/components/ui/Progress.tsx +59 -0
  94. package/src/components/ui/Rating.tsx +65 -0
  95. package/src/components/ui/SearchInput.tsx +106 -0
  96. package/src/components/ui/SegmentedControl.tsx +44 -0
  97. package/src/components/ui/ShowcaseWrapper.tsx +136 -0
  98. package/src/components/ui/Stat.tsx +39 -0
  99. package/src/components/ui/Stepper.tsx +75 -0
  100. package/src/components/ui/Table.tsx +55 -0
  101. package/src/components/ui/Tabs.tsx +53 -0
  102. package/src/components/ui/Terminal.tsx +54 -0
  103. package/src/components/ui/ThemeDomSync.tsx +17 -0
  104. package/src/components/ui/ThemeManager.tsx +18 -0
  105. package/src/components/ui/ThemeSwitcher.tsx +46 -0
  106. package/src/components/ui/Timeline.tsx +60 -0
  107. package/src/components/ui/Toast.tsx +70 -0
  108. package/src/components/ui/Typography.tsx +129 -0
  109. package/src/components/ui/index.ts +92 -0
  110. package/src/styles/themes.css +118 -0
@@ -0,0 +1,190 @@
1
+ import {
2
+ HogTrendLineChart,
3
+ InsightDoughnutChart,
4
+ InsightHorizontalBarChart,
5
+ InsightPolarAreaChart,
6
+ InsightStackedBarChart,
7
+ InsightVerticalBarChart,
8
+ } from "@/components/charts";
9
+ import { DashboardWell, InsightShell, InsightShellHeader } from "@/components/dashboard";
10
+ import { ShowcaseWrapper } from "@/components/ui";
11
+
12
+ export default function ChartShowcase() {
13
+ const code = `import { HogTrendLineChart, InsightDoughnutChart, InsightHorizontalBarChart, InsightPolarAreaChart, InsightStackedBarChart, InsightVerticalBarChart } from "the-old-ui";
14
+ import { DashboardWell, InsightShell, InsightShellHeader } from "the-old-ui";
15
+
16
+ <DashboardWell>
17
+ <div className="grid gap-6 lg:grid-cols-2">
18
+ <InsightShell className="min-h-0">
19
+ <InsightShellHeader
20
+ title="Trends (hog-charts model · canvas + d3-scale)"
21
+ subtitle={
22
+ <>
23
+ Same <code className="ph-kbd">Series</code> shape as PostHog (<code className="ph-kbd">stroke.pattern</code>,
24
+ <code className="ph-kbd">fill.opacity</code>), 2&nbsp;px round-capped strokes, horizontal grid, dashed
25
+ crosshair, multi-series hover ring.
26
+ </>
27
+ }
28
+ />
29
+ <HogTrendLineChart />
30
+ </InsightShell>
31
+
32
+ <InsightShell className="min-h-0">
33
+ <InsightShellHeader
34
+ title="Vertical bars (Chart.js)"
35
+ subtitle={
36
+ <>
37
+ Bar charts in PostHog&apos;s UI are also built on <code className="ph-kbd">TimeSeriesBarChart</code> /
38
+ <code className="ph-kbd">BarChart</code> in hog-charts; this tile uses Chart.js with the same semantic
39
+ <code className="ph-kbd">--ph-data-*</code> colours.
40
+ </>
41
+ }
42
+ />
43
+ <InsightVerticalBarChart />
44
+ </InsightShell>
45
+
46
+ <InsightShell className="min-h-0 lg:col-span-2">
47
+ <InsightShellHeader
48
+ title="Horizontal bar (Chart.js)"
49
+ subtitle={
50
+ <>
51
+ <code className="ph-kbd">indexAxis: &quot;y&quot;</code> mirrors long-label breakdowns (URLs, flags, cohorts).
52
+ </>
53
+ }
54
+ />
55
+ <InsightHorizontalBarChart />
56
+ </InsightShell>
57
+
58
+ <InsightShell className="min-h-0 lg:col-span-2">
59
+ <InsightShellHeader
60
+ title="Stacked breakdown (Chart.js)"
61
+ subtitle={
62
+ <>
63
+ Multiple datasets with <code className="ph-kbd">stacked: true</code> — analogous to multi-series bar
64
+ layouts in insights.
65
+ </>
66
+ }
67
+ />
68
+ <InsightStackedBarChart />
69
+ </InsightShell>
70
+
71
+ <InsightShell className="min-h-0">
72
+ <InsightShellHeader
73
+ title="Doughnut (Chart.js)"
74
+ subtitle={
75
+ <>
76
+ <code className="ph-kbd">ArcElement</code> + <code className="ph-kbd">cutout</code> for donut slices;
77
+ legend and tooltip use the same CSS-variable palette.
78
+ </>
79
+ }
80
+ />
81
+ <InsightDoughnutChart />
82
+ </InsightShell>
83
+
84
+ <InsightShell className="min-h-0">
85
+ <InsightShellHeader
86
+ title="Polar area (Chart.js)"
87
+ subtitle={
88
+ <>
89
+ <code className="ph-kbd">RadialLinearScale</code> for spoke grid lines; useful for compact multi-metric
90
+ comparisons.
91
+ </>
92
+ }
93
+ />
94
+ <InsightPolarAreaChart />
95
+ </InsightShell>
96
+ </div>
97
+ </DashboardWell>`;
98
+
99
+ return (
100
+ <ShowcaseWrapper
101
+ title="Charts (PostHog-style)"
102
+ description="In the open-source PostHog app, most product-analytics trend lines and areas are drawn with hog-charts — Canvas 2D plus D3 scales. Chart.js remains for some chart types."
103
+ code={code}
104
+ filename="ChartExample.tsx"
105
+ >
106
+ <DashboardWell>
107
+ <div className="grid gap-6 lg:grid-cols-2">
108
+ <InsightShell className="min-h-0">
109
+ <InsightShellHeader
110
+ title="Trends (hog-charts model · canvas + d3-scale)"
111
+ subtitle={
112
+ <>
113
+ Same <code className="ph-kbd">Series</code> shape as PostHog (<code className="ph-kbd">stroke.pattern</code>,
114
+ <code className="ph-kbd">fill.opacity</code>), 2&nbsp;px round-capped strokes, horizontal grid, dashed
115
+ crosshair, multi-series hover ring.
116
+ </>
117
+ }
118
+ />
119
+ <HogTrendLineChart />
120
+ </InsightShell>
121
+
122
+ <InsightShell className="min-h-0">
123
+ <InsightShellHeader
124
+ title="Vertical bars (Chart.js)"
125
+ subtitle={
126
+ <>
127
+ Bar charts in PostHog&apos;s UI are also built on <code className="ph-kbd">TimeSeriesBarChart</code> /
128
+ <code className="ph-kbd">BarChart</code> in hog-charts; this tile uses Chart.js with the same semantic
129
+ <code className="ph-kbd">--ph-data-*</code> colours.
130
+ </>
131
+ }
132
+ />
133
+ <InsightVerticalBarChart />
134
+ </InsightShell>
135
+
136
+ <InsightShell className="min-h-0 lg:col-span-2">
137
+ <InsightShellHeader
138
+ title="Horizontal bar (Chart.js)"
139
+ subtitle={
140
+ <>
141
+ <code className="ph-kbd">indexAxis: &quot;y&quot;</code> mirrors long-label breakdowns (URLs, flags, cohorts).
142
+ </>
143
+ }
144
+ />
145
+ <InsightHorizontalBarChart />
146
+ </InsightShell>
147
+
148
+ <InsightShell className="min-h-0 lg:col-span-2">
149
+ <InsightShellHeader
150
+ title="Stacked breakdown (Chart.js)"
151
+ subtitle={
152
+ <>
153
+ Multiple datasets with <code className="ph-kbd">stacked: true</code> — analogous to multi-series bar
154
+ layouts in insights.
155
+ </>
156
+ }
157
+ />
158
+ <InsightStackedBarChart />
159
+ </InsightShell>
160
+
161
+ <InsightShell className="min-h-0">
162
+ <InsightShellHeader
163
+ title="Doughnut (Chart.js)"
164
+ subtitle={
165
+ <>
166
+ <code className="ph-kbd">ArcElement</code> + <code className="ph-kbd">cutout</code> for donut slices;
167
+ legend and tooltip use the same CSS-variable palette.
168
+ </>
169
+ }
170
+ />
171
+ <InsightDoughnutChart />
172
+ </InsightShell>
173
+
174
+ <InsightShell className="min-h-0">
175
+ <InsightShellHeader
176
+ title="Polar area (Chart.js)"
177
+ subtitle={
178
+ <>
179
+ <code className="ph-kbd">RadialLinearScale</code> for spoke grid lines; useful for compact multi-metric
180
+ comparisons.
181
+ </>
182
+ }
183
+ />
184
+ <InsightPolarAreaChart />
185
+ </InsightShell>
186
+ </div>
187
+ </DashboardWell>
188
+ </ShowcaseWrapper>
189
+ );
190
+ }
@@ -0,0 +1,56 @@
1
+ import { IconQueryEditor } from "@/components/icons";
2
+ import { ComponentDocs, ShowcaseWrapper, Terminal } from "@/components/ui";
3
+
4
+ export default function CodeMockupShowcase() {
5
+ const code = `import { Terminal } from "the-old-ui";
6
+
7
+ <Terminal
8
+ title="sandbox · posthog-wizard"
9
+ lines={[
10
+ { text: "❯ bun add posthog-js", color: "text-neutral-600" },
11
+ { text: "● added posthog-js@1...", color: "text-emerald-400" },
12
+ { text: "❯ POSTHOG_KEY=...", color: "text-neutral-600" },
13
+ ]}
14
+ />`;
15
+
16
+ return (
17
+ <ShowcaseWrapper
18
+ title="Terminal capture"
19
+ description="Terminal and replay shells for documentation, demos, and embedded developer flows."
20
+ code={code}
21
+ filename="TerminalExample.tsx"
22
+ docs={
23
+ <ComponentDocs
24
+ rows={[
25
+ { name: "title", type: "string", description: "Window title in the header." },
26
+ { name: "lines", type: "Array<{ text; color? }>", description: "Terminal lines to render." },
27
+ { name: "children", type: "ReactNode", description: "Custom content instead of lines." },
28
+ ]}
29
+ />
30
+ }
31
+ >
32
+ <div className="space-y-10">
33
+ <Terminal
34
+ title="sandbox · posthog-wizard"
35
+ lines={[
36
+ { text: "❯ bun add posthog-js", color: "text-neutral-600" },
37
+ { text: "● added posthog-js@1...", color: "text-emerald-400" },
38
+ { text: "❯ POSTHOG_KEY=...", color: "text-neutral-600" },
39
+ ]}
40
+ />
41
+
42
+ <div className="rounded-xl border border-ph-border shadow-ph-md">
43
+ <header className="relative flex items-center justify-center border-b border-ph-border px-10 py-3 text-[11px] font-semibold text-ph-mutedtext">
44
+ <span className="absolute left-5 top-4 h-px w-[88%] rounded-full bg-ph-border opacity-70" />
45
+ Replay preview
46
+ </header>
47
+ <div className="flex flex-col items-center gap-5 bg-ph-toolbar px-6 py-14 text-ph-subtle">
48
+ <IconQueryEditor className="h-14 w-14 opacity-50" />
49
+ <p className="text-center font-semibold text-ph-ink">Session snapshot shell</p>
50
+ <p className="max-w-xs text-center text-xs">Mirrors bordered frame around insight embeds rather than DaisyUI mocks.</p>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ </ShowcaseWrapper>
55
+ );
56
+ }
@@ -0,0 +1,117 @@
1
+ import type { CSSProperties } from "react";
2
+ import { ShowcaseWrapper } from "@/components/ui";
3
+
4
+ const brandSurface: { label: string; token: string; style: CSSProperties; textClass: string }[] = [
5
+ { label: "Brand orange", token: "--ph-accent", style: { background: "var(--ph-accent)" }, textClass: "text-white" },
6
+ { label: "Brand blue", token: "--ph-blue", style: { background: "var(--ph-blue)" }, textClass: "text-white" },
7
+ { label: "Purple accent", token: "--ph-purple", style: { background: "var(--ph-purple)" }, textClass: "text-white" },
8
+ { label: "Canvas (3000-50)", token: "--ph-canvas", style: { background: "var(--ph-canvas)" }, textClass: "text-ph-ink ring-1 ring-inset ring-ph-border" },
9
+ { label: "Muted surface", token: "--ph-muted", style: { background: "var(--ph-muted)" }, textClass: "text-ph-ink ring-1 ring-inset ring-ph-border" },
10
+ { label: "White surface", token: "--ph-surface", style: { background: "var(--ph-surface)" }, textClass: "text-ph-ink ring-1 ring-inset ring-ph-border" },
11
+ { label: "Border", token: "--ph-border", style: { background: "var(--ph-border)" }, textClass: "text-ph-ink" },
12
+ { label: "Success", token: "--ph-success", style: { background: "var(--ph-success)" }, textClass: "text-white" },
13
+ { label: "Warning", token: "--ph-warning", style: { background: "var(--ph-warning)" }, textClass: "text-white" },
14
+ { label: "Danger", token: "--ph-danger", style: { background: "var(--ph-danger)" }, textClass: "text-white" },
15
+ { label: "Info", token: "--ph-info", style: { background: "var(--ph-info)" }, textClass: "text-white" },
16
+ ];
17
+
18
+ const dataSeries = [1, 2, 3, 4, 5, 6, 7].map((n) => ({
19
+ label: `Data ${n}`,
20
+ token: `--ph-data-${n}`,
21
+ style: { background: `var(--ph-data-${n})` } as CSSProperties,
22
+ textClass: "text-white",
23
+ }));
24
+
25
+ const productRail = [
26
+ { label: "Session replay", token: "--ph-product-session-replay", style: { background: "var(--ph-product-session-replay)" } as CSSProperties },
27
+ { label: "Product analytics", token: "--ph-product-product-analytics", style: { background: "var(--ph-product-product-analytics)" } as CSSProperties },
28
+ { label: "Data pipeline", token: "--ph-product-data-pipeline", style: { background: "var(--ph-product-data-pipeline)" } as CSSProperties },
29
+ { label: "Feature flags", token: "--ph-product-feature-flags", style: { background: "var(--ph-product-feature-flags)" } as CSSProperties },
30
+ { label: "Experiments", token: "--ph-product-experiments", style: { background: "var(--ph-product-experiments)" } as CSSProperties },
31
+ { label: "Data warehouse", token: "--ph-product-data-warehouse", style: { background: "var(--ph-product-data-warehouse)" } as CSSProperties },
32
+ { label: "Surveys", token: "--ph-product-surveys", style: { background: "var(--ph-product-surveys)" } as CSSProperties },
33
+ ].map((row) => ({ ...row, textClass: "text-white" }));
34
+
35
+ function SwatchGrid({
36
+ title,
37
+ description,
38
+ items,
39
+ }: {
40
+ title: string;
41
+ description: string;
42
+ items: { label: string; token: string; style: CSSProperties; textClass: string }[];
43
+ }) {
44
+ return (
45
+ <div>
46
+ <h3 className="mb-1 text-xs font-semibold uppercase tracking-wider text-ph-mutedtext">{title}</h3>
47
+ <p className="mb-3 text-sm text-ph-subtle">{description}</p>
48
+ <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
49
+ {items.map((c) => (
50
+ <div
51
+ key={c.token}
52
+ className={`rounded-[var(--ph-radius-app)] p-5 ${c.textClass}`}
53
+ style={{
54
+ ...c.style,
55
+ boxShadow: "var(--ph-shadow-elevation-3000)",
56
+ }}
57
+ >
58
+ <p className="text-sm font-semibold">{c.label}</p>
59
+ <p className="mt-1 font-mono text-[11px] opacity-90">{c.token}</p>
60
+ </div>
61
+ ))}
62
+ </div>
63
+ </div>
64
+ );
65
+ }
66
+
67
+ export default function ColorPalette() {
68
+ const code = `/* CSS variables update with the active theme */
69
+
70
+ // Brand & surfaces
71
+ background: var(--ph-accent); // Brand orange
72
+ background: var(--ph-canvas); // Canvas
73
+ background: var(--ph-surface); // White surface
74
+ border-color: var(--ph-border); // Hairline borders
75
+
76
+ // Semantic status
77
+ color: var(--ph-success); // Success green
78
+ color: var(--ph-danger); // Danger red
79
+ color: var(--ph-warning); // Warning amber
80
+ color: var(--ph-info); // Info blue
81
+
82
+ // Data series (charts)
83
+ background: var(--ph-data-1); // Primary
84
+ background: var(--ph-data-2); // Secondary
85
+ // ... up to ph-data-7
86
+
87
+ // Product rail
88
+ background: var(--ph-product-session-replay);
89
+ background: var(--ph-product-product-analytics);`;
90
+
91
+ return (
92
+ <ShowcaseWrapper
93
+ title="Colour tokens"
94
+ description="Tokens update with the Theme select in the header — surfaces, accents, chart series, and product rail colours all swap together."
95
+ code={code}
96
+ filename="Tokens.css"
97
+ >
98
+ <div className="space-y-10">
99
+ <SwatchGrid
100
+ title="Brand & surfaces"
101
+ description="Core UI chrome and semantic status hues."
102
+ items={brandSurface}
103
+ />
104
+ <SwatchGrid
105
+ title="Insight data series"
106
+ description="Default trend / breakdown palette."
107
+ items={dataSeries}
108
+ />
109
+ <SwatchGrid
110
+ title="Product rail"
111
+ description="Saturated nav / marketing tiles."
112
+ items={productRail}
113
+ />
114
+ </div>
115
+ </ShowcaseWrapper>
116
+ );
117
+ }
@@ -0,0 +1,48 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { Button, CommandPalette, ComponentDocs, ShowcaseWrapper } from "@/components/ui";
5
+ import { IconSearch, IconBolt, IconTuning, IconHome, IconPerson } from "@/components/icons";
6
+
7
+ export default function CommandPaletteShowcase() {
8
+ const [isOpen, setIsOpen] = useState(false);
9
+
10
+ const items = [
11
+ { id: "1", label: "Go to Dashboard", shortcut: "Cmd+D", icon: <IconHome className="h-5 w-5" />, onSelect: () => {} },
12
+ { id: "2", label: "Search Events", shortcut: "Cmd+K", icon: <IconSearch className="h-5 w-5" />, onSelect: () => {} },
13
+ { id: "3", label: "Run Query", shortcut: "Cmd+R", icon: <IconBolt className="h-5 w-5" />, onSelect: () => {} },
14
+ { id: "4", label: "Settings", shortcut: "Cmd+,", icon: <IconTuning className="h-5 w-5" />, onSelect: () => {} },
15
+ { id: "5", label: "Profile", icon: <IconPerson className="h-5 w-5" />, onSelect: () => {} },
16
+ ];
17
+
18
+ const code = `import { Button, CommandPalette } from "the-old-ui";
19
+ import { IconSearch, IconBolt, IconTuning, IconHome, IconPerson } from "the-old-ui";
20
+
21
+ <div className="ph-panel">
22
+ <Button onClick={() => setIsOpen(true)}>Open Command Palette</Button>
23
+ <CommandPalette items={items} isOpen={isOpen} onClose={() => setIsOpen(false)} />
24
+ </div>`;
25
+
26
+ return (
27
+ <ShowcaseWrapper
28
+ title="Command Palette"
29
+ description="Application command launcher with controlled open state and typed item actions."
30
+ code={code}
31
+ filename="CommandPaletteExample.tsx"
32
+ docs={
33
+ <ComponentDocs
34
+ rows={[
35
+ { name: "items", type: "{ id; label; shortcut?; icon?; onSelect }[]", description: "Commands shown in the palette." },
36
+ { name: "isOpen", type: "boolean", description: "Controls palette visibility." },
37
+ { name: "onClose", type: "() => void", description: "Called by escape, backdrop, or selection." },
38
+ ]}
39
+ />
40
+ }
41
+ >
42
+ <div className="ph-panel">
43
+ <Button onClick={() => setIsOpen(true)}>Open Command Palette</Button>
44
+ <CommandPalette items={items} isOpen={isOpen} onClose={() => setIsOpen(false)} />
45
+ </div>
46
+ </ShowcaseWrapper>
47
+ );
48
+ }
@@ -0,0 +1,43 @@
1
+ import { ShowcaseWrapper } from "@/components/ui";
2
+
3
+ export default function CountdownShowcase() {
4
+ const code = `
5
+
6
+ <div className="ph-panel">
7
+ <p className="mb-6 text-sm text-ph-subtle">Static split — swap for synced timers once you plug in real experiment deadlines.</p>
8
+ <div className="flex flex-wrap justify-center gap-3 text-ph-ink sm:justify-start">
9
+ {[
10
+ { v: "04", label: "Days" },
11
+ { v: "12", label: "Hrs" },
12
+ { v: "33", label: "Min" },
13
+ { v: "09", label: "Sec" },
14
+ ].map(({ v, label }) => (
15
+ <div key={label} className="flex min-w-[4.75rem] flex-col items-center rounded-xl border border-ph-border bg-ph-surface px-4 py-3 shadow-ph">
16
+ <span className="text-3xl font-bold tabular-nums">{v}</span>
17
+ <span className="text-[11px] font-semibold uppercase tracking-wider text-ph-mutedtext">{label}</span>
18
+ </div>
19
+ ))}
20
+ </div>
21
+ </div>`;
22
+
23
+ return (
24
+ <ShowcaseWrapper title="Countdown motif" code={code} filename="CountdownExample.tsx">
25
+ <div className="ph-panel">
26
+ <p className="mb-6 text-sm text-ph-subtle">Static split — swap for synced timers once you plug in real experiment deadlines.</p>
27
+ <div className="flex flex-wrap justify-center gap-3 text-ph-ink sm:justify-start">
28
+ {[
29
+ { v: "04", label: "Days" },
30
+ { v: "12", label: "Hrs" },
31
+ { v: "33", label: "Min" },
32
+ { v: "09", label: "Sec" },
33
+ ].map(({ v, label }) => (
34
+ <div key={label} className="flex min-w-[4.75rem] flex-col items-center rounded-xl border border-ph-border bg-ph-surface px-4 py-3 shadow-ph">
35
+ <span className="text-3xl font-bold tabular-nums">{v}</span>
36
+ <span className="text-[11px] font-semibold uppercase tracking-wider text-ph-mutedtext">{label}</span>
37
+ </div>
38
+ ))}
39
+ </div>
40
+ </div>
41
+ </ShowcaseWrapper>
42
+ );
43
+ }
@@ -0,0 +1,191 @@
1
+ import { IconAreaChart, IconArrowUp, IconCohort, IconPlus } from "@/components/icons";
2
+ import {
3
+ DashboardFiltersBar,
4
+ DashboardGrid,
5
+ DashboardInsightPlaceholder,
6
+ DashboardKpiCard,
7
+ DashboardToolbar,
8
+ DashboardWell,
9
+ InsightMiniCard,
10
+ } from "@/components/dashboard";
11
+ import { Button, ShowcaseWrapper } from "@/components/ui";
12
+
13
+ const insightCards = [
14
+ {
15
+ title: "Weekly active users",
16
+ subtitle: "Last 14 days · product analytics",
17
+ ribbonColour: "var(--ph-product-product-analytics)",
18
+ heights: [40, 55, 48, 62, 58, 70, 52, 45, 68, 72, 65, 80, 75, 88],
19
+ },
20
+ {
21
+ title: "Session length",
22
+ subtitle: "Median minutes · replay cohort",
23
+ ribbonColour: "var(--ph-product-session-replay)",
24
+ heights: [52, 48, 45, 50, 55, 60, 58, 54, 50, 48, 55, 60, 58, 62],
25
+ },
26
+ {
27
+ title: "Flag evaluations",
28
+ subtitle: "Per minute · infrastructure",
29
+ ribbonColour: "var(--ph-product-feature-flags)",
30
+ heights: [30, 35, 42, 38, 45, 50, 48, 52, 55, 58, 54, 50, 48, 55],
31
+ },
32
+ ] as const;
33
+
34
+ export default function DashboardShowcase() {
35
+ const code = `import { IconAreaChart, IconArrowUp, IconCohort, IconPlus } from "the-old-ui";
36
+ import { DashboardFiltersBar, DashboardGrid, DashboardInsightPlaceholder, DashboardKpiCard, DashboardToolbar, DashboardWell, InsightMiniCard } from "the-old-ui";
37
+ import { Button } from "the-old-ui";
38
+
39
+ <DashboardWell className="space-y-6">
40
+ <DashboardToolbar
41
+ title="Marketing overview"
42
+ description="Mock layout · spacing and elevation only"
43
+ actions={
44
+ <Button variant="secondary" size="sm">
45
+ Edit layout
46
+ </Button>
47
+ }
48
+ />
49
+
50
+ <DashboardFiltersBar className="text-xs">
51
+ <span className="font-semibold text-ph-ink">Last 14 days</span>
52
+ <span className="text-ph-mutedtext">·</span>
53
+ <span>Global cohort</span>
54
+ <Button variant="ghost" size="xs" className="rounded-md px-2">
55
+ Breakdown
56
+ </Button>
57
+ </DashboardFiltersBar>
58
+
59
+ <div className="grid gap-4 md:grid-cols-3">
60
+ <DashboardKpiCard
61
+ icon={<IconArrowUp className="text-ph-brand" aria-hidden />}
62
+ label="Event volume"
63
+ value={<span className="text-ph-brand tabular-nums">2.6M</span>}
64
+ footer={
65
+ <>
66
+ <span className="font-semibold text-emerald-700">▲ 21%</span> vs previous window
67
+ </>
68
+ }
69
+ />
70
+ <DashboardKpiCard
71
+ icon={<IconCohort className="text-ph-blue" aria-hidden />}
72
+ label="Weekly active users"
73
+ value={<span className="text-ph-blue tabular-nums">12.8K</span>}
74
+ footer="Stable vs trailing 28-day baseline"
75
+ />
76
+ <DashboardKpiCard
77
+ icon={<IconAreaChart className="text-ph-purple" aria-hidden />}
78
+ label="Experiments exposing"
79
+ value={<span className="text-ph-purple tabular-nums">4</span>}
80
+ footer="Flags + multivariates counted"
81
+ />
82
+ </div>
83
+
84
+ <DashboardGrid>
85
+ {insightCards.map((card) => (
86
+ <InsightMiniCard
87
+ key={card.title}
88
+ title={card.title}
89
+ subtitle={card.subtitle}
90
+ ribbonColour={card.ribbonColour}
91
+ heights={card.heights}
92
+ />
93
+ ))}
94
+ </DashboardGrid>
95
+
96
+ <div className="grid gap-4 md:grid-cols-2">
97
+ <InsightMiniCard
98
+ title="Activation funnel"
99
+ subtitle="Mock · drop-off by step"
100
+ ribbonColour="var(--ph-product-experiments)"
101
+ heights={[88, 72, 58, 44, 32, 28, 24, 22, 20, 18, 16, 15, 14, 13]}
102
+ />
103
+ <DashboardInsightPlaceholder>
104
+ <IconPlus className="h-8 w-8 text-ph-mutedtext group-hover:text-ph-brand" aria-hidden />
105
+ <span className="text-sm font-medium text-ph-subtle group-hover:text-ph-ink">Add insight</span>
106
+ <span className="max-w-[14rem] text-xs text-ph-mutedtext">Opens the same picker pattern your app uses for new tiles.</span>
107
+ </DashboardInsightPlaceholder>
108
+ </div>
109
+ </DashboardWell>`;
110
+
111
+ return (
112
+ <ShowcaseWrapper
113
+ title="Dashboard shells"
114
+ description="Inset canvas (DashboardWell) and raised insight tiles (InsightShell / InsightMiniCard) mirror how the PostHog app frames dashboards."
115
+ code={code}
116
+ filename="DashboardExample.tsx"
117
+ >
118
+ <DashboardWell className="space-y-6">
119
+ <DashboardToolbar
120
+ title="Marketing overview"
121
+ description="Mock layout · spacing and elevation only"
122
+ actions={
123
+ <Button variant="secondary" size="sm">
124
+ Edit layout
125
+ </Button>
126
+ }
127
+ />
128
+
129
+ <DashboardFiltersBar className="text-xs">
130
+ <span className="font-semibold text-ph-ink">Last 14 days</span>
131
+ <span className="text-ph-mutedtext">·</span>
132
+ <span>Global cohort</span>
133
+ <Button variant="ghost" size="xs" className="rounded-md px-2">
134
+ Breakdown
135
+ </Button>
136
+ </DashboardFiltersBar>
137
+
138
+ <div className="grid gap-4 md:grid-cols-3">
139
+ <DashboardKpiCard
140
+ icon={<IconArrowUp className="text-ph-brand" aria-hidden />}
141
+ label="Event volume"
142
+ value={<span className="text-ph-brand tabular-nums">2.6M</span>}
143
+ footer={
144
+ <>
145
+ <span className="font-semibold text-emerald-700">▲ 21%</span> vs previous window
146
+ </>
147
+ }
148
+ />
149
+ <DashboardKpiCard
150
+ icon={<IconCohort className="text-ph-blue" aria-hidden />}
151
+ label="Weekly active users"
152
+ value={<span className="text-ph-blue tabular-nums">12.8K</span>}
153
+ footer="Stable vs trailing 28-day baseline"
154
+ />
155
+ <DashboardKpiCard
156
+ icon={<IconAreaChart className="text-ph-purple" aria-hidden />}
157
+ label="Experiments exposing"
158
+ value={<span className="text-ph-purple tabular-nums">4</span>}
159
+ footer="Flags + multivariates counted"
160
+ />
161
+ </div>
162
+
163
+ <DashboardGrid>
164
+ {insightCards.map((card) => (
165
+ <InsightMiniCard
166
+ key={card.title}
167
+ title={card.title}
168
+ subtitle={card.subtitle}
169
+ ribbonColour={card.ribbonColour}
170
+ heights={card.heights}
171
+ />
172
+ ))}
173
+ </DashboardGrid>
174
+
175
+ <div className="grid gap-4 md:grid-cols-2">
176
+ <InsightMiniCard
177
+ title="Activation funnel"
178
+ subtitle="Mock · drop-off by step"
179
+ ribbonColour="var(--ph-product-experiments)"
180
+ heights={[88, 72, 58, 44, 32, 28, 24, 22, 20, 18, 16, 15, 14, 13]}
181
+ />
182
+ <DashboardInsightPlaceholder>
183
+ <IconPlus className="h-8 w-8 text-ph-mutedtext group-hover:text-ph-brand" aria-hidden />
184
+ <span className="text-sm font-medium text-ph-subtle group-hover:text-ph-ink">Add insight</span>
185
+ <span className="max-w-[14rem] text-xs text-ph-mutedtext">Opens the same picker pattern your app uses for new tiles.</span>
186
+ </DashboardInsightPlaceholder>
187
+ </div>
188
+ </DashboardWell>
189
+ </ShowcaseWrapper>
190
+ );
191
+ }