@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.
- package/dist/chunk-5HSOBJ4F.mjs +5968 -0
- package/dist/{index-D1RTT2Ap.d.mts → index-BgG8Homu.d.mts} +419 -2
- package/dist/{index-D1RTT2Ap.d.ts → index-BgG8Homu.d.ts} +419 -2
- package/dist/index.d.mts +198 -95
- package/dist/index.d.ts +198 -95
- package/dist/index.js +2995 -1136
- package/dist/index.mjs +629 -735
- package/dist/ui.d.mts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +1986 -156
- package/dist/ui.mjs +76 -3
- package/package.json +4 -14
- package/src/app/globals.css +976 -2
- package/src/components/charts/index.ts +9 -8
- package/src/components/charts/quill/BarChart.tsx +85 -0
- package/src/components/charts/quill/FunnelChart.tsx +49 -0
- package/src/components/charts/quill/InsightShell.tsx +27 -0
- package/src/components/charts/quill/MetricCard.tsx +44 -0
- package/src/components/charts/quill/PieChart.tsx +81 -0
- package/src/components/charts/quill/Sparkline.tsx +57 -0
- package/src/components/charts/quill/TimeSeriesLineChart.tsx +62 -0
- package/src/components/charts/quill/index.ts +9 -0
- package/src/components/icons/icons.tsx +2 -0
- package/src/components/icons/index.ts +3 -0
- package/src/components/icons/lemon-brand-icons.tsx +16 -0
- package/src/components/icons/lemon-category-icons.tsx +72 -0
- package/src/components/icons/lemon-icons.tsx +57 -0
- package/src/components/sections/IconShowcase.tsx +110 -7
- package/src/components/sections/NewComponentsShowcase.tsx +1052 -0
- package/src/components/sections/ProductLayoutsShowcase.tsx +57 -117
- package/src/components/sections/QuillChartShowcase.tsx +92 -0
- package/src/components/sections/QuillDashboardShowcase.tsx +149 -0
- package/src/components/sections/SidebarShowcase.tsx +152 -0
- package/src/components/sections/TableShowcase.tsx +2 -0
- package/src/components/sections/TooltipShowcase.tsx +19 -25
- package/src/components/ui/AlertDialog.tsx +62 -0
- package/src/components/ui/AppLayout.tsx +27 -0
- package/src/components/ui/Autocomplete.tsx +106 -0
- package/src/components/ui/Banner.tsx +63 -0
- package/src/components/ui/ButtonGroup.tsx +16 -0
- package/src/components/ui/Chip.tsx +46 -0
- package/src/components/ui/Collapsible.tsx +46 -0
- package/src/components/ui/Combobox.tsx +119 -0
- package/src/components/ui/ContextMenu.tsx +81 -0
- package/src/components/ui/DataTable.tsx +133 -0
- package/src/components/ui/DatePicker.tsx +96 -0
- package/src/components/ui/Dialog.tsx +75 -0
- package/src/components/ui/Divider.tsx +39 -0
- package/src/components/ui/Dot.tsx +32 -0
- package/src/components/ui/InputGroup.tsx +16 -0
- package/src/components/ui/Lettermark.tsx +47 -0
- package/src/components/ui/Link.tsx +32 -0
- package/src/components/ui/LoadingBar.tsx +25 -0
- package/src/components/ui/Menubar.tsx +66 -0
- package/src/components/ui/Metric.tsx +34 -0
- package/src/components/ui/NumberField.tsx +76 -0
- package/src/components/ui/Popover.tsx +73 -0
- package/src/components/ui/ProgressCircle.tsx +63 -0
- package/src/components/ui/Resizable.tsx +71 -0
- package/src/components/ui/Row.tsx +51 -0
- package/src/components/ui/ScrollArea.tsx +54 -0
- package/src/components/ui/Sidebar.tsx +77 -0
- package/src/components/ui/Snack.tsx +48 -0
- package/src/components/ui/Spinner.tsx +30 -0
- package/src/components/ui/Splotch.tsx +33 -0
- package/src/components/ui/Table.tsx +2 -0
- package/src/components/ui/Tag.tsx +65 -0
- package/src/components/ui/Toggle.tsx +62 -0
- package/src/components/ui/Tooltip.test.tsx +58 -0
- package/src/components/ui/Tooltip.tsx +211 -0
- package/src/components/ui/Widget.tsx +31 -0
- package/src/components/ui/index.ts +275 -21
- package/dist/chunk-FDMD3IIN.mjs +0 -3831
- package/src/components/charts/ph-insight-charts.tsx +0 -162
- package/src/components/dashboard/DashboardFiltersBar.tsx +0 -19
- package/src/components/dashboard/DashboardGrid.tsx +0 -23
- package/src/components/dashboard/DashboardInsightPlaceholder.tsx +0 -37
- package/src/components/dashboard/DashboardKpiCard.tsx +0 -25
- package/src/components/dashboard/DashboardToolbar.tsx +0 -23
- package/src/components/dashboard/DashboardWell.tsx +0 -10
- package/src/components/dashboard/InsightMiniCard.tsx +0 -26
- package/src/components/dashboard/InsightShell.tsx +0 -37
- package/src/components/dashboard/InsightShellHeader.tsx +0 -22
- package/src/components/dashboard/MiniTrendBars.tsx +0 -51
- package/src/components/dashboard/index.ts +0 -31
- package/src/components/dashboard/types.ts +0 -9
- package/src/components/sections/ChartShowcase.tsx +0 -190
- package/src/components/sections/DashboardShowcase.tsx +0 -191
- package/src/components/sections/StatShowcase.tsx +0 -129
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useMemo, useState } from "react";
|
|
4
|
-
import "@/lib/chart/register-chartjs";
|
|
5
|
-
import { Bar, Doughnut, PolarArea } from "react-chartjs-2";
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
buildDoughnutDemo,
|
|
9
|
-
buildHorizontalBarDemo,
|
|
10
|
-
buildPolarAreaDemo,
|
|
11
|
-
buildStackedBarDemo,
|
|
12
|
-
buildVerticalBarDemo,
|
|
13
|
-
} from "@/lib/chart/ph-chart-options";
|
|
14
|
-
import { useChartTokens } from "@/lib/chart/use-ph-chart-tokens";
|
|
15
|
-
import { buildHogChartTheme } from "@/lib/hog-charts-lite/build-theme";
|
|
16
|
-
import { CanvasTrendLineChart } from "@/lib/hog-charts-lite/CanvasTrendLineChart";
|
|
17
|
-
|
|
18
|
-
const DEMO_LABELS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
19
|
-
|
|
20
|
-
function useClientMounted(): boolean {
|
|
21
|
-
const [mounted, setMounted] = useState(false);
|
|
22
|
-
|
|
23
|
-
useEffect(() => setMounted(true), []);
|
|
24
|
-
|
|
25
|
-
return mounted;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface ChartSkeletonProps {
|
|
29
|
-
className?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function ChartSkeleton({ className = "h-[280px]" }: ChartSkeletonProps) {
|
|
33
|
-
return (
|
|
34
|
-
<div
|
|
35
|
-
className={`w-full animate-pulse rounded-lemon bg-ph-muted ${className}`}
|
|
36
|
-
aria-hidden
|
|
37
|
-
/>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function HogTrendLineChart() {
|
|
42
|
-
const mounted = useClientMounted();
|
|
43
|
-
const tokens = useChartTokens();
|
|
44
|
-
const theme = useMemo(() => buildHogChartTheme(tokens), [tokens]);
|
|
45
|
-
|
|
46
|
-
const series = useMemo(
|
|
47
|
-
() => [
|
|
48
|
-
{
|
|
49
|
-
key: "pageview",
|
|
50
|
-
label: "$pageview",
|
|
51
|
-
data: [4200, 5100, 4800, 6200, 5900, 3100, 2800],
|
|
52
|
-
color: tokens.series[0],
|
|
53
|
-
fill: { opacity: 0.35 },
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
key: "signup",
|
|
57
|
-
label: "signup_completed",
|
|
58
|
-
data: [920, 990, 940, 1040, 1012, 540, 510],
|
|
59
|
-
color: tokens.series[1],
|
|
60
|
-
stroke: { pattern: [5, 5] as number[] },
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
[tokens.series],
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
if (!mounted) {
|
|
67
|
-
return <ChartSkeleton />;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<div className="relative h-[280px] w-full min-h-[220px]">
|
|
72
|
-
<CanvasTrendLineChart
|
|
73
|
-
labels={DEMO_LABELS}
|
|
74
|
-
series={series}
|
|
75
|
-
theme={theme}
|
|
76
|
-
showGrid
|
|
77
|
-
showCrosshair
|
|
78
|
-
className="h-full min-h-[220px]"
|
|
79
|
-
/>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function InsightVerticalBarChart() {
|
|
85
|
-
const mounted = useClientMounted();
|
|
86
|
-
const tokens = useChartTokens();
|
|
87
|
-
const config = useMemo(() => buildVerticalBarDemo(tokens), [tokens]);
|
|
88
|
-
|
|
89
|
-
if (!mounted) {
|
|
90
|
-
return <ChartSkeleton />;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<div className="relative h-[280px] w-full min-h-[220px]">
|
|
95
|
-
<Bar data={config.data} options={config.options} redraw={false} />
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function InsightHorizontalBarChart() {
|
|
101
|
-
const mounted = useClientMounted();
|
|
102
|
-
const tokens = useChartTokens();
|
|
103
|
-
const config = useMemo(() => buildHorizontalBarDemo(tokens), [tokens]);
|
|
104
|
-
|
|
105
|
-
if (!mounted) {
|
|
106
|
-
return <ChartSkeleton className="h-[320px]" />;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<div className="relative h-[320px] w-full min-h-[260px]">
|
|
111
|
-
<Bar data={config.data} options={config.options} redraw={false} />
|
|
112
|
-
</div>
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function InsightStackedBarChart() {
|
|
117
|
-
const mounted = useClientMounted();
|
|
118
|
-
const tokens = useChartTokens();
|
|
119
|
-
const config = useMemo(() => buildStackedBarDemo(tokens), [tokens]);
|
|
120
|
-
|
|
121
|
-
if (!mounted) {
|
|
122
|
-
return <ChartSkeleton className="h-[300px]" />;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return (
|
|
126
|
-
<div className="relative h-[300px] w-full min-h-[240px]">
|
|
127
|
-
<Bar data={config.data} options={config.options} redraw={false} />
|
|
128
|
-
</div>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function InsightDoughnutChart() {
|
|
133
|
-
const mounted = useClientMounted();
|
|
134
|
-
const tokens = useChartTokens();
|
|
135
|
-
const config = useMemo(() => buildDoughnutDemo(tokens), [tokens]);
|
|
136
|
-
|
|
137
|
-
if (!mounted) {
|
|
138
|
-
return <ChartSkeleton className="h-[260px]" />;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return (
|
|
142
|
-
<div className="relative mx-auto h-[260px] w-full max-w-[280px] min-h-[220px]">
|
|
143
|
-
<Doughnut data={config.data} options={config.options} redraw={false} />
|
|
144
|
-
</div>
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function InsightPolarAreaChart() {
|
|
149
|
-
const mounted = useClientMounted();
|
|
150
|
-
const tokens = useChartTokens();
|
|
151
|
-
const config = useMemo(() => buildPolarAreaDemo(tokens), [tokens]);
|
|
152
|
-
|
|
153
|
-
if (!mounted) {
|
|
154
|
-
return <ChartSkeleton className="h-[280px]" />;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return (
|
|
158
|
-
<div className="relative mx-auto h-[280px] w-full max-w-[320px] min-h-[240px]">
|
|
159
|
-
<PolarArea data={config.data} options={config.options} redraw={false} />
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Raised strip reminiscent of dashboard date-range / cohort / breakdown controls.
|
|
6
|
-
* Pass pills or selects as children.
|
|
7
|
-
*/
|
|
8
|
-
export function DashboardFiltersBar({ className, ...props }: ComponentPropsWithoutRef<"div">) {
|
|
9
|
-
return (
|
|
10
|
-
<div
|
|
11
|
-
className={cn(
|
|
12
|
-
"flex flex-wrap items-center gap-2 rounded-[var(--ph-radius-app)] border border-solid bg-ph-surface px-3 py-2 text-sm text-ph-subtle [border-color:var(--ph-border-control)]",
|
|
13
|
-
"[box-shadow:var(--ph-chrome-inset-face-top),var(--ph-chrome-inset-face-bottom),var(--ph-shadow-elevation-3000)]",
|
|
14
|
-
className,
|
|
15
|
-
)}
|
|
16
|
-
{...props}
|
|
17
|
-
/>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface DashboardGridProps extends ComponentPropsWithoutRef<"div"> {
|
|
5
|
-
/**
|
|
6
|
-
* Preset breakpoints: 1 col → md:2 cols → xl:3 (matches common insight grids).
|
|
7
|
-
* Override with your own `className` if you need 4-up or single column.
|
|
8
|
-
*/
|
|
9
|
-
preset?: "insights" | "dense";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const presetClass: Record<NonNullable<DashboardGridProps["preset"]>, string> = {
|
|
13
|
-
insights: "grid gap-4 md:grid-cols-2 xl:grid-cols-3",
|
|
14
|
-
dense: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export function DashboardGrid({
|
|
18
|
-
preset = "insights",
|
|
19
|
-
className,
|
|
20
|
-
...props
|
|
21
|
-
}: DashboardGridProps) {
|
|
22
|
-
return <div className={cn(presetClass[preset], className)} {...props} />;
|
|
23
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface DashboardInsightPlaceholderProps extends ComponentPropsWithoutRef<"button"> {
|
|
5
|
-
/** Accessible name when `children` does not include visible text. */
|
|
6
|
-
label?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Mimics PostHog’s empty dashboard slot (“add insight”).
|
|
11
|
-
* Renders `<button>` so you can wire `onClick` → palette / modal.
|
|
12
|
-
*
|
|
13
|
-
* **`onClick` and other event props:** use this inside a Client Component (or a wrapper
|
|
14
|
-
* marked `'use client'`). Server Components cannot serialise function props.
|
|
15
|
-
*/
|
|
16
|
-
export function DashboardInsightPlaceholder({
|
|
17
|
-
label = "Add insight",
|
|
18
|
-
className,
|
|
19
|
-
children,
|
|
20
|
-
type = "button",
|
|
21
|
-
...props
|
|
22
|
-
}: DashboardInsightPlaceholderProps) {
|
|
23
|
-
return (
|
|
24
|
-
<button
|
|
25
|
-
type={type}
|
|
26
|
-
aria-label={label}
|
|
27
|
-
className={cn(
|
|
28
|
-
"ph-dashboard-placeholder group text-left outline-none transition",
|
|
29
|
-
"focus-visible:ring-2 focus-visible:ring-ph-brand focus-visible:ring-offset-2",
|
|
30
|
-
className,
|
|
31
|
-
)}
|
|
32
|
-
{...props}
|
|
33
|
-
>
|
|
34
|
-
{children != null ? children : <span className="font-medium text-ph-subtle group-hover:text-ph-ink">{label}</span>}
|
|
35
|
-
</button>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface DashboardKpiCardProps extends ComponentPropsWithoutRef<"article"> {
|
|
5
|
-
/** Upper label (tabular small caps styling via `.ph-stat-label`). */
|
|
6
|
-
label: ReactNode;
|
|
7
|
-
/** Main KPI value. */
|
|
8
|
-
value: ReactNode;
|
|
9
|
-
/** Supporting line beneath the value (Δ %, qualifier, etc.). */
|
|
10
|
-
footer?: ReactNode;
|
|
11
|
-
/** Optional decorative icon aligned with headline stats across the PostHog app. */
|
|
12
|
-
icon?: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function DashboardKpiCard({ label, value, footer, icon, className, children, ...props }: DashboardKpiCardProps) {
|
|
16
|
-
return (
|
|
17
|
-
<article className={cn("ph-stat", className)} {...props}>
|
|
18
|
-
{icon != null ? <div className="mb-2 [&>svg]:h-7 [&>svg]:w-7">{icon}</div> : null}
|
|
19
|
-
<div className="ph-stat-label">{label}</div>
|
|
20
|
-
<div className="ph-stat-val">{value}</div>
|
|
21
|
-
{footer != null ? <p className="mt-1 text-xs text-ph-subtle">{footer}</p> : null}
|
|
22
|
-
{children}
|
|
23
|
-
</article>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface DashboardToolbarProps {
|
|
5
|
-
/** Dashboard / tab title (matches PostHog H3 weight on canvases). */
|
|
6
|
-
title: string;
|
|
7
|
-
description?: string;
|
|
8
|
-
/** Right-aligned actions slot (buttons, dropdown triggers, etc.). */
|
|
9
|
-
actions?: ReactNode;
|
|
10
|
-
className?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function DashboardToolbar({ title, description, actions, className }: DashboardToolbarProps) {
|
|
14
|
-
return (
|
|
15
|
-
<div className={cn("flex flex-wrap items-baseline justify-between gap-4", className)}>
|
|
16
|
-
<div className="min-w-0">
|
|
17
|
-
<h3 className="text-lg font-bold text-ph-ink">{title}</h3>
|
|
18
|
-
{description ? <p className="mt-0.5 text-sm text-ph-mutedtext">{description}</p> : null}
|
|
19
|
-
</div>
|
|
20
|
-
{actions != null ? <div className="flex shrink-0 flex-wrap items-center gap-2">{actions}</div> : null}
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface DashboardWellProps extends ComponentPropsWithoutRef<"div"> {
|
|
5
|
-
/** Passed through to inner div; merges with `.ph-dashboard-well` */
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function DashboardWell({ className, ...props }: DashboardWellProps) {
|
|
9
|
-
return <div className={cn("ph-dashboard-well", className)} {...props} />;
|
|
10
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { InsightShellProps } from "./InsightShell";
|
|
2
|
-
import { InsightShell } from "./InsightShell";
|
|
3
|
-
import { InsightShellHeader } from "./InsightShellHeader";
|
|
4
|
-
import { MiniTrendBars } from "./MiniTrendBars";
|
|
5
|
-
|
|
6
|
-
export interface InsightMiniCardProps extends Omit<InsightShellProps, "children"> {
|
|
7
|
-
title: string;
|
|
8
|
-
subtitle?: string;
|
|
9
|
-
heights: readonly number[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** Opinionated insight tile: coloured ribbon + headline + subtitle + mini Hog-style bar sparkline. */
|
|
13
|
-
export function InsightMiniCard({
|
|
14
|
-
title,
|
|
15
|
-
subtitle,
|
|
16
|
-
heights,
|
|
17
|
-
ribbonColour,
|
|
18
|
-
...shellProps
|
|
19
|
-
}: InsightMiniCardProps) {
|
|
20
|
-
return (
|
|
21
|
-
<InsightShell ribbonColour={ribbonColour} {...shellProps}>
|
|
22
|
-
<InsightShellHeader title={title} subtitle={subtitle} />
|
|
23
|
-
<MiniTrendBars heights={heights} />
|
|
24
|
-
</InsightShell>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import type { RibbonColour } from "./types";
|
|
3
|
-
import { cn } from "@/lib/cn";
|
|
4
|
-
|
|
5
|
-
export interface InsightShellProps extends ComponentPropsWithoutRef<"article"> {
|
|
6
|
-
/**
|
|
7
|
-
* Left ribbon fill; omit or pass empty string for a flat card (no ribbon column).
|
|
8
|
-
* Prefer `var(--ph-product-*)` or `var(--ph-data-*)` tokens from `globals.css`.
|
|
9
|
-
*/
|
|
10
|
-
ribbonColour?: RibbonColour | null;
|
|
11
|
-
/** Extra classes on the padded body column (e.g. `gap-4`). */
|
|
12
|
-
bodyClassName?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function InsightShell({
|
|
16
|
-
ribbonColour,
|
|
17
|
-
bodyClassName,
|
|
18
|
-
className,
|
|
19
|
-
children,
|
|
20
|
-
...props
|
|
21
|
-
}: InsightShellProps) {
|
|
22
|
-
const ribbon =
|
|
23
|
-
ribbonColour != null && String(ribbonColour).trim() !== "" ? String(ribbonColour).trim() : null;
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<article className={cn("ph-insight-shell flex-row", className)} {...props}>
|
|
27
|
-
{ribbon != null ? (
|
|
28
|
-
<div
|
|
29
|
-
className="ph-insight-shell__ribbon min-h-[7rem] shrink-0 self-stretch"
|
|
30
|
-
style={{ background: ribbon }}
|
|
31
|
-
aria-hidden
|
|
32
|
-
/>
|
|
33
|
-
) : null}
|
|
34
|
-
<div className={cn("flex min-w-0 flex-1 flex-col gap-3 p-4", bodyClassName)}>{children}</div>
|
|
35
|
-
</article>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
export interface InsightShellHeaderProps {
|
|
5
|
-
title: ReactNode;
|
|
6
|
-
subtitle?: ReactNode;
|
|
7
|
-
/** Trailing widgets (menus, fullscreen, cohort badge). */
|
|
8
|
-
actions?: ReactNode;
|
|
9
|
-
className?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function InsightShellHeader({ title, subtitle, actions, className }: InsightShellHeaderProps) {
|
|
13
|
-
return (
|
|
14
|
-
<header className={cn("flex gap-3", actions != null ? "items-start justify-between" : "", className)}>
|
|
15
|
-
<div className="min-w-0 flex-1">
|
|
16
|
-
<h4 className="font-semibold leading-snug text-ph-ink">{title}</h4>
|
|
17
|
-
{subtitle != null ? <p className="mt-0.5 text-xs text-ph-mutedtext">{subtitle}</p> : null}
|
|
18
|
-
</div>
|
|
19
|
-
{actions != null ? <div className="flex shrink-0 items-center gap-1">{actions}</div> : null}
|
|
20
|
-
</header>
|
|
21
|
-
);
|
|
22
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties } from "react";
|
|
2
|
-
import { cn } from "@/lib/cn";
|
|
3
|
-
|
|
4
|
-
const DEFAULT_SERIES_CYCLE = [1, 2, 3, 4, 5, 6, 7] as const;
|
|
5
|
-
|
|
6
|
-
export interface MiniTrendBarsProps {
|
|
7
|
-
/** Normalised heights 0–100 for each bar (% of chart row). */
|
|
8
|
-
heights: readonly number[];
|
|
9
|
-
/** Tailwind height of the bars row (flex align-end). Default matches gallery `h-28`. */
|
|
10
|
-
rowClassName?: string;
|
|
11
|
-
/**
|
|
12
|
-
* Map bar index → CSS `--ph-data-*` token index (1–7).
|
|
13
|
-
* Default cycles through PostHog’s default trend palette.
|
|
14
|
-
*/
|
|
15
|
-
seriesResolver?: (index: number, height: number) => number;
|
|
16
|
-
className?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function clampPct(n: number): number {
|
|
20
|
-
if (!Number.isFinite(n)) {
|
|
21
|
-
return 0;
|
|
22
|
-
}
|
|
23
|
-
return Math.max(0, Math.min(100, n));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function MiniTrendBars({
|
|
27
|
-
heights,
|
|
28
|
-
rowClassName = "h-28",
|
|
29
|
-
seriesResolver,
|
|
30
|
-
className,
|
|
31
|
-
}: MiniTrendBarsProps) {
|
|
32
|
-
const resolveSeries =
|
|
33
|
-
seriesResolver ??
|
|
34
|
-
((i: number) => DEFAULT_SERIES_CYCLE[i % DEFAULT_SERIES_CYCLE.length] ?? 1);
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<div className={cn("flex items-end gap-0.5", rowClassName, className)}>
|
|
38
|
-
{heights.map((raw, i) => {
|
|
39
|
-
const pct = clampPct(raw);
|
|
40
|
-
const series = resolveSeries(i, pct);
|
|
41
|
-
const style = {
|
|
42
|
-
height: `${pct}%`,
|
|
43
|
-
background: `var(--ph-data-${String(series)})`,
|
|
44
|
-
minHeight: pct > 0 ? 4 : 0,
|
|
45
|
-
} satisfies CSSProperties;
|
|
46
|
-
|
|
47
|
-
return <div key={`bar-${String(i)}`} className="min-h-0 flex-1 rounded-t-[3px]" style={style} />;
|
|
48
|
-
})}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export { cn } from "@/lib/cn";
|
|
2
|
-
export type { RibbonColour, Slot } from "./types";
|
|
3
|
-
|
|
4
|
-
export { DashboardWell } from "./DashboardWell";
|
|
5
|
-
export type { DashboardWellProps } from "./DashboardWell";
|
|
6
|
-
|
|
7
|
-
export { DashboardToolbar } from "./DashboardToolbar";
|
|
8
|
-
export type { DashboardToolbarProps } from "./DashboardToolbar";
|
|
9
|
-
|
|
10
|
-
export { DashboardGrid } from "./DashboardGrid";
|
|
11
|
-
export type { DashboardGridProps } from "./DashboardGrid";
|
|
12
|
-
|
|
13
|
-
export { DashboardFiltersBar } from "./DashboardFiltersBar";
|
|
14
|
-
|
|
15
|
-
export { DashboardKpiCard } from "./DashboardKpiCard";
|
|
16
|
-
export type { DashboardKpiCardProps } from "./DashboardKpiCard";
|
|
17
|
-
|
|
18
|
-
export { DashboardInsightPlaceholder } from "./DashboardInsightPlaceholder";
|
|
19
|
-
export type { DashboardInsightPlaceholderProps } from "./DashboardInsightPlaceholder";
|
|
20
|
-
|
|
21
|
-
export { InsightShell } from "./InsightShell";
|
|
22
|
-
export type { InsightShellProps } from "./InsightShell";
|
|
23
|
-
|
|
24
|
-
export { InsightShellHeader } from "./InsightShellHeader";
|
|
25
|
-
export type { InsightShellHeaderProps } from "./InsightShellHeader";
|
|
26
|
-
|
|
27
|
-
export { MiniTrendBars } from "./MiniTrendBars";
|
|
28
|
-
export type { MiniTrendBarsProps } from "./MiniTrendBars";
|
|
29
|
-
|
|
30
|
-
export { InsightMiniCard } from "./InsightMiniCard";
|
|
31
|
-
export type { InsightMiniCardProps } from "./InsightMiniCard";
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Any CSS `<color>` usable in `background`, e.g. `var(--ph-product-session-replay)` or `#1d4aff`.
|
|
5
|
-
*/
|
|
6
|
-
export type RibbonColour = string;
|
|
7
|
-
|
|
8
|
-
/** Children slot pattern used across dashboard primitives */
|
|
9
|
-
export type Slot = ReactNode;
|
|
@@ -1,190 +0,0 @@
|
|
|
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 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'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: "y"</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 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'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: "y"</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
|
-
}
|