@alpic-ai/ui 1.160.0 → 1.162.0

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 (58) hide show
  1. package/dist/components/accordion-card.d.mts +1 -5
  2. package/dist/components/accordion-card.mjs +1 -5
  3. package/dist/components/accordion.d.mts +1 -5
  4. package/dist/components/accordion.mjs +1 -5
  5. package/dist/components/attachment-tile.d.mts +0 -5
  6. package/dist/components/chart-legend.d.mts +4 -1
  7. package/dist/components/chart-legend.mjs +21 -7
  8. package/dist/components/chart-primitives.d.mts +3 -8
  9. package/dist/components/chart-primitives.mjs +3 -8
  10. package/dist/components/combobox.d.mts +0 -1
  11. package/dist/components/line-chart.d.mts +3 -1
  12. package/dist/components/line-chart.mjs +7 -4
  13. package/dist/components/select-trigger-variants.d.mts +1 -5
  14. package/dist/components/select-trigger-variants.mjs +1 -5
  15. package/dist/components/table.d.mts +1 -5
  16. package/dist/components/task-progress.d.mts +1 -4
  17. package/dist/lib/chart-palette.d.mts +1 -20
  18. package/dist/lib/chart-palette.mjs +1 -20
  19. package/dist/lib/chart.d.mts +1 -4
  20. package/dist/lib/chart.mjs +2 -11
  21. package/package.json +5 -5
  22. package/src/components/accordion-card.tsx +1 -5
  23. package/src/components/accordion.tsx +1 -5
  24. package/src/components/attachment-tile.tsx +0 -5
  25. package/src/components/avatar.tsx +0 -2
  26. package/src/components/bar-chart.tsx +1 -2
  27. package/src/components/bar-list.tsx +1 -2
  28. package/src/components/chart-legend.tsx +47 -10
  29. package/src/components/chart-primitives.tsx +3 -9
  30. package/src/components/combobox.tsx +1 -29
  31. package/src/components/dropdown-menu.tsx +0 -12
  32. package/src/components/form.tsx +0 -4
  33. package/src/components/heatmap-chart.tsx +4 -10
  34. package/src/components/line-chart.tsx +16 -3
  35. package/src/components/select-trigger-variants.ts +1 -5
  36. package/src/components/select.tsx +0 -10
  37. package/src/components/sidebar.tsx +0 -2
  38. package/src/components/table.tsx +1 -5
  39. package/src/components/tabs.tsx +1 -18
  40. package/src/components/tag.tsx +0 -6
  41. package/src/components/task-progress.tsx +2 -14
  42. package/src/components/wizard.tsx +0 -6
  43. package/src/lib/chart-palette.ts +3 -22
  44. package/src/lib/chart.ts +3 -15
  45. package/src/stories/button.stories.tsx +1 -15
  46. package/src/stories/combobox.stories.tsx +0 -12
  47. package/src/stories/dropdown-menu.stories.tsx +0 -4
  48. package/src/stories/form.stories.tsx +0 -6
  49. package/src/stories/heatmap-chart.stories.tsx +0 -1
  50. package/src/stories/input-group.stories.tsx +0 -4
  51. package/src/stories/input.stories.tsx +0 -8
  52. package/src/stories/line-chart.stories.tsx +120 -80
  53. package/src/stories/sidebar.stories.tsx +1 -4
  54. package/src/stories/skeleton.stories.tsx +0 -2
  55. package/src/stories/table.stories.tsx +0 -5
  56. package/src/stories/tabs.stories.tsx +0 -11
  57. package/src/stories/toggle-group.stories.tsx +0 -5
  58. package/src/stories/wizard.stories.tsx +0 -4
@@ -2,8 +2,7 @@ import { ArrowRight, Plus, Sparkles } from "lucide-react";
2
2
 
3
3
  import { Button } from "../components/button";
4
4
 
5
- // Simulated states via className matches Figma page layout:
6
- // variants stacked top-to-bottom, states left-to-right.
5
+ // Hover states are simulated via className; layout matches the Figma page (variants top-to-bottom, states left-to-right).
7
6
 
8
7
  const VARIANT_LABEL = "type-text-xs text-muted-foreground w-20 shrink-0";
9
8
  const STATE_HEADER = "type-text-xs text-muted-foreground font-medium w-32 text-center";
@@ -16,7 +15,6 @@ const ICON_STATE_HEADER = "type-text-xs text-muted-foreground font-medium w-16 t
16
15
  export const AllVariants = () => {
17
16
  return (
18
17
  <div className="flex flex-col gap-3 p-8">
19
- {/* ── Text buttons ────────────────────────────────────────────────── */}
20
18
  <span className={SECTION_HEADER}>Text</span>
21
19
 
22
20
  <div className={ROW}>
@@ -26,7 +24,6 @@ export const AllVariants = () => {
26
24
  <div className={STATE_HEADER}>Loading</div>
27
25
  </div>
28
26
 
29
- {/* Primary */}
30
27
  <div className={ROW}>
31
28
  <span className={VARIANT_LABEL}>Primary</span>
32
29
  <div className={CELL}>
@@ -46,7 +43,6 @@ export const AllVariants = () => {
46
43
  </div>
47
44
  </div>
48
45
 
49
- {/* Secondary */}
50
46
  <div className={ROW}>
51
47
  <span className={VARIANT_LABEL}>Secondary</span>
52
48
  <div className={CELL}>
@@ -66,7 +62,6 @@ export const AllVariants = () => {
66
62
  </div>
67
63
  </div>
68
64
 
69
- {/* Tertiary */}
70
65
  <div className={ROW}>
71
66
  <span className={VARIANT_LABEL}>Tertiary</span>
72
67
  <div className={CELL}>
@@ -86,7 +81,6 @@ export const AllVariants = () => {
86
81
  </div>
87
82
  </div>
88
83
 
89
- {/* Link color */}
90
84
  <div className={ROW}>
91
85
  <span className={VARIANT_LABEL}>Link</span>
92
86
  <div className={CELL}>
@@ -104,7 +98,6 @@ export const AllVariants = () => {
104
98
  </div>
105
99
  </div>
106
100
 
107
- {/* Link gray */}
108
101
  <div className={ROW}>
109
102
  <span className={VARIANT_LABEL}>Link muted</span>
110
103
  <div className={CELL}>
@@ -122,7 +115,6 @@ export const AllVariants = () => {
122
115
  </div>
123
116
  </div>
124
117
 
125
- {/* Destructive */}
126
118
  <div className={ROW}>
127
119
  <span className={VARIANT_LABEL}>Destructive</span>
128
120
  <div className={CELL}>
@@ -142,7 +134,6 @@ export const AllVariants = () => {
142
134
  </div>
143
135
  </div>
144
136
 
145
- {/* ── Icon only ───────────────────────────────────────────────────── */}
146
137
  <span className={SECTION_HEADER}>Icon only</span>
147
138
 
148
139
  <div className={ROW}>
@@ -213,7 +204,6 @@ export const AllVariants = () => {
213
204
  </div>
214
205
  </div>
215
206
 
216
- {/* ── Icon rounded ────────────────────────────────────────────────── */}
217
207
  <span className={SECTION_HEADER}>Icon rounded</span>
218
208
 
219
209
  <div className={ROW}>
@@ -284,7 +274,6 @@ export const AllVariants = () => {
284
274
  </div>
285
275
  </div>
286
276
 
287
- {/* ── Pill ──────────────────────────────────────────────────────────── */}
288
277
  <span className={SECTION_HEADER}>Pill</span>
289
278
 
290
279
  <div className="flex items-center gap-3">
@@ -302,7 +291,6 @@ export const AllVariants = () => {
302
291
  </Button>
303
292
  </div>
304
293
 
305
- {/* ── With icon (leading) ──────────────────────────────────────────── */}
306
294
  <span className={SECTION_HEADER}>With icon</span>
307
295
 
308
296
  <div className="flex items-center gap-3">
@@ -323,7 +311,6 @@ export const AllVariants = () => {
323
311
  </Button>
324
312
  </div>
325
313
 
326
- {/* ── CTA (animated gradient ring) ────────────────────────────────── */}
327
314
  <span className={SECTION_HEADER}>CTA — animated</span>
328
315
  <p className="type-text-xs text-muted-foreground -mt-2 max-w-md">
329
316
  Hover to rotate the conic gradient around the border and ignite the soft halo.
@@ -345,7 +332,6 @@ export const AllVariants = () => {
345
332
  </Button>
346
333
  </div>
347
334
 
348
- {/* ── asChild ─────────────────────────────────────────────────────── */}
349
335
  <span className={SECTION_HEADER}>asChild</span>
350
336
 
351
337
  <div className="flex items-center gap-3">
@@ -15,8 +15,6 @@ import {
15
15
  } from "../components/combobox";
16
16
  import { CommandItem } from "../components/command";
17
17
 
18
- /* ── With search ──────────────────────────────────────────────────────────── */
19
-
20
18
  const branches = ["main", "develop", "feature/auth", "feature/dashboard", "fix/login-bug", "release/v2.0"];
21
19
 
22
20
  function SearchCombobox() {
@@ -44,8 +42,6 @@ function SearchCombobox() {
44
42
  );
45
43
  }
46
44
 
47
- /* ── Custom trigger content (avatars + supporting text) ──────────────────── */
48
-
49
45
  const people = [
50
46
  { id: "olivia", name: "Olivia Rhye", handle: "@olivia" },
51
47
  { id: "phoenix", name: "Phoenix Baker", handle: "@phoenix" },
@@ -90,8 +86,6 @@ function AvatarCombobox() {
90
86
  );
91
87
  }
92
88
 
93
- /* ── With CommandItem action ─────────────────────────────────────────────── */
94
-
95
89
  const namespaces = [
96
90
  { id: "acme", name: "acme-corp" },
97
91
  { id: "personal", name: "johndoe" },
@@ -127,8 +121,6 @@ function CommandActionCombobox() {
127
121
  );
128
122
  }
129
123
 
130
- /* ── Grouped with headings ───────────────────────────────────────────────── */
131
-
132
124
  function GroupedCombobox() {
133
125
  const [value, setValue] = useState<string | null>(null);
134
126
  return (
@@ -154,8 +146,6 @@ function GroupedCombobox() {
154
146
  );
155
147
  }
156
148
 
157
- /* ── Multi-select with tags ───────────────────────────────────────────────── */
158
-
159
149
  function MultiCombobox() {
160
150
  const [values, setValues] = useState<string[]>(["phoenix", "olivia"]);
161
151
  return (
@@ -182,8 +172,6 @@ function MultiCombobox() {
182
172
  );
183
173
  }
184
174
 
185
- /* ── Story ────────────────────────────────────────────────────────────────── */
186
-
187
175
  export const AllVariants: Story = () => (
188
176
  <div className="grid grid-cols-1 gap-10 p-10 md:grid-cols-2">
189
177
  <div className="flex flex-col gap-1.5">
@@ -34,7 +34,6 @@ import {
34
34
 
35
35
  export const AllVariants: Story = () => (
36
36
  <div className="flex flex-col gap-10 p-10">
37
- {/* Basic with icons & shortcuts */}
38
37
  <div className="flex flex-col gap-1.5">
39
38
  <p className="type-text-xs font-medium text-subtle-foreground">Default with icons &amp; shortcuts</p>
40
39
  <DropdownMenu>
@@ -122,7 +121,6 @@ export const AllVariants: Story = () => (
122
121
  </DropdownMenu>
123
122
  </div>
124
123
 
125
- {/* Destructive variant */}
126
124
  <div className="flex flex-col gap-1.5">
127
125
  <p className="type-text-xs font-medium text-subtle-foreground">Destructive item</p>
128
126
  <DropdownMenu>
@@ -143,7 +141,6 @@ export const AllVariants: Story = () => (
143
141
  </DropdownMenu>
144
142
  </div>
145
143
 
146
- {/* Header with avatar */}
147
144
  <div className="flex flex-col gap-1.5">
148
145
  <p className="type-text-xs font-medium text-subtle-foreground">With header (avatar group)</p>
149
146
  <DropdownMenu>
@@ -173,7 +170,6 @@ export const AllVariants: Story = () => (
173
170
  </DropdownMenu>
174
171
  </div>
175
172
 
176
- {/* Disabled items */}
177
173
  <div className="flex flex-col gap-1.5">
178
174
  <p className="type-text-xs font-medium text-subtle-foreground">Disabled items</p>
179
175
  <DropdownMenu>
@@ -13,8 +13,6 @@ import {
13
13
  TextareaField,
14
14
  } from "../components/form";
15
15
 
16
- /* ── Types ───────────────────────────────────────────────────────────────── */
17
-
18
16
  interface CreateProjectForm {
19
17
  email: string;
20
18
  role: string;
@@ -43,8 +41,6 @@ const capabilities = [
43
41
  { value: "admin", label: "Admin" },
44
42
  ];
45
43
 
46
- /* ── Composed Form ───────────────────────────────────────────────────────── */
47
-
48
44
  function ComposedForm() {
49
45
  const form = useForm<CreateProjectForm>({
50
46
  defaultValues: {
@@ -141,8 +137,6 @@ function ComposedForm() {
141
137
  );
142
138
  }
143
139
 
144
- /* ── Story ────────────────────────────────────────────────────────────────── */
145
-
146
140
  export const AllVariants: Story = () => (
147
141
  <div className="flex flex-col gap-3">
148
142
  <p className="type-text-xs font-medium text-subtle-foreground uppercase tracking-wide">
@@ -18,7 +18,6 @@ function mulberry32(seed: number) {
18
18
  };
19
19
  }
20
20
 
21
- // Long-format activity rows: one record per (day, hour) with a working-hours hump.
22
21
  const ACTIVITY = (() => {
23
22
  const random = mulberry32(99);
24
23
  const rows: Array<{ day: string; hour: string; sessions: number }> = [];
@@ -7,7 +7,6 @@ const SECTION_HEADER = "type-text-xs font-medium text-muted-foreground uppercase
7
7
 
8
8
  export const AllVariants: Story = () => (
9
9
  <div className="flex flex-col gap-6 p-8 max-w-lg">
10
- {/* Textarea with block-end addon */}
11
10
  <span className={SECTION_HEADER}>Textarea + block-end footer</span>
12
11
  <InputGroup>
13
12
  <InputGroupTextarea placeholder="Type a message…" />
@@ -21,7 +20,6 @@ export const AllVariants: Story = () => (
21
20
  </InputGroupAddon>
22
21
  </InputGroup>
23
22
 
24
- {/* Inline-start addon */}
25
23
  <span className={SECTION_HEADER}>Inline-start addon (icon)</span>
26
24
  <InputGroup>
27
25
  <InputGroupAddon align="inline-start">
@@ -34,7 +32,6 @@ export const AllVariants: Story = () => (
34
32
  />
35
33
  </InputGroup>
36
34
 
37
- {/* Inline-end addon */}
38
35
  <span className={SECTION_HEADER}>Inline-end addon (button)</span>
39
36
  <InputGroup>
40
37
  <input
@@ -49,7 +46,6 @@ export const AllVariants: Story = () => (
49
46
  </InputGroupAddon>
50
47
  </InputGroup>
51
48
 
52
- {/* Disabled state */}
53
49
  <span className={SECTION_HEADER}>Disabled</span>
54
50
  <InputGroup>
55
51
  <InputGroupTextarea placeholder="Cannot type here…" disabled />
@@ -7,11 +7,9 @@ const SECTION_HEADER = "type-text-xs font-medium text-muted-foreground uppercase
7
7
 
8
8
  export const AllVariants: Story = () => (
9
9
  <div className="flex flex-col gap-6 p-8 max-w-sm">
10
- {/* Default */}
11
10
  <span className={SECTION_HEADER}>Default</span>
12
11
  <Input id="default" placeholder="alice@example.com" />
13
12
 
14
- {/* With label + hint */}
15
13
  <span className={SECTION_HEADER}>With label + hint</span>
16
14
  <Input
17
15
  id="with-label"
@@ -21,7 +19,6 @@ export const AllVariants: Story = () => (
21
19
  hint="This is a hint text to help user."
22
20
  />
23
21
 
24
- {/* With tooltip */}
25
22
  <span className={SECTION_HEADER}>With tooltip</span>
26
23
  <Input
27
24
  id="with-tooltip"
@@ -31,7 +28,6 @@ export const AllVariants: Story = () => (
31
28
  placeholder="alice@example.com"
32
29
  />
33
30
 
34
- {/* Error */}
35
31
  <span className={SECTION_HEADER}>Error</span>
36
32
  <Input
37
33
  id="error"
@@ -41,7 +37,6 @@ export const AllVariants: Story = () => (
41
37
  error="Please enter a valid email address."
42
38
  />
43
39
 
44
- {/* Disabled */}
45
40
  <span className={SECTION_HEADER}>Disabled</span>
46
41
  <Input
47
42
  id="disabled"
@@ -51,15 +46,12 @@ export const AllVariants: Story = () => (
51
46
  disabled
52
47
  />
53
48
 
54
- {/* Leading icon */}
55
49
  <span className={SECTION_HEADER}>Leading icon (email)</span>
56
50
  <Input id="leading-icon" label="Email" required placeholder="alice@example.com" leadingIcon={<Mail />} />
57
51
 
58
- {/* Leading text (website) */}
59
52
  <span className={SECTION_HEADER}>Leading text</span>
60
53
  <Input id="leading-text" label="Website" required placeholder="www.example.com" leadingText="http://" />
61
54
 
62
- {/* Small size */}
63
55
  <span className={SECTION_HEADER}>Small size</span>
64
56
  <Input id="sm-default" size="sm" placeholder="alice@example.com" label="Email" />
65
57
 
@@ -1,4 +1,5 @@
1
1
  import type { Story } from "@ladle/react";
2
+ import { useState } from "react";
2
3
 
3
4
  import { ChartCard } from "../components/chart-card";
4
5
  import { LineChart } from "../components/line-chart";
@@ -37,7 +38,8 @@ const genLatency = (seed: number) => {
37
38
  return Array.from({ length }, (_, index) => {
38
39
  p50 = Math.max(120, p50 + (rnd() - 0.48) * 40);
39
40
  p95 = Math.max(p50 + 200, p95 + (rnd() - 0.46) * 120);
40
- return { t: hourLabel(index, length), p50: Math.round(p50), p95: Math.round(p95 * (index === 19 ? 1.7 : 1)) };
41
+ const spiked = Math.round(p95 * (index === 19 ? 1.7 : 1));
42
+ return { t: hourLabel(index, length), p50: Math.round(p50), p95: spiked, p99: Math.round(spiked * 1.6) };
41
43
  });
42
44
  };
43
45
 
@@ -64,83 +66,121 @@ const ms = (value: number) => `${value}ms`;
64
66
  const tokensSpark = tokens.map((row) => row.v);
65
67
  const latencyPeak = latency.reduce((best, row) => (row.p95 > best.p95 ? row : best));
66
68
 
67
- export const AllVariants: Story = () => (
68
- <div className="mx-auto max-w-[1600px] p-8">
69
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3">
70
- <ChartCard
71
- palette="cyan"
72
- accent="left"
73
- kicker="Last 24h"
74
- title="Sessions"
75
- description="Full-width · left accent"
76
- className="md:col-span-2 xl:col-span-3"
77
- >
78
- <LineChart
79
- data={compare}
80
- index="t"
81
- series={[
82
- { key: "claude", name: "Claude" },
83
- { key: "chatgpt", name: "ChatGPT" },
84
- ]}
85
- lastValueLabel
86
- legend
87
- valueFormatter={nf}
88
- />
89
- </ChartCard>
90
-
91
- <ChartCard palette="magenta" kicker="Last 24h" title="Output tokens" description="Single series · value flags">
92
- <Stat value="1.4M" unit="tokens" delta={{ value: 8.1, direction: "up" }} sparkline={tokensSpark} />
93
- <LineChart data={tokens} index="t" series={[{ key: "v", name: "tokens" }]} valueFlags valueFormatter={fmtK} />
94
- </ChartCard>
95
-
96
- <ChartCard palette="magenta" kicker="Last 24h" title="Request latency" description="p50 vs p95 · SLA band + peak">
97
- <Stat value="240ms" unit="p50 · current" delta={{ value: 4.2, direction: "down", invert: true }} />
98
- <LineChart
99
- data={latency}
100
- index="t"
101
- series={[
102
- { key: "p50", name: "p50" },
103
- { key: "p95", name: "p95", dashed: true, color: "#9b5de5" },
104
- ]}
105
- referenceLine={{ y: 1000, label: "SLA 1s", band: true }}
106
- markers={[{ x: latencyPeak.t, y: latencyPeak.p95, label: "peak", color: "#9b5de5" }]}
107
- legend
108
- valueFormatter={ms}
109
- />
110
- </ChartCard>
111
-
112
- <ChartCard palette="cyan" kicker="Last 24h" title="Sessions" description="Claude vs ChatGPT · last values">
113
- <LineChart
114
- data={compare}
115
- index="t"
116
- series={[
117
- { key: "claude", name: "Claude" },
118
- { key: "chatgpt", name: "ChatGPT" },
119
- ]}
120
- lastValueLabel
121
- legend
122
- valueFormatter={nf}
123
- />
124
- </ChartCard>
125
-
126
- <ChartCard palette="cyan" kicker="Last 24h" title="Throughput" description="Dots · stepped curve">
127
- <LineChart
128
- data={tokens}
129
- index="t"
130
- series={[{ key: "v", name: "tokens" }]}
131
- curve="step"
132
- dots
133
- valueFormatter={fmtK}
134
- />
135
- </ChartCard>
136
-
137
- <ChartCard palette="magenta" kicker="State" title="Loading" description="Mono spinner placeholder">
138
- <LineChart data={[]} index="t" series={[{ key: "v", name: "tokens" }]} loading />
139
- </ChartCard>
140
-
141
- <ChartCard palette="magenta" kicker="State" title="Empty" description="No data in range">
142
- <LineChart data={[]} index="t" series={[{ key: "v", name: "tokens" }]} />
143
- </ChartCard>
69
+ const percentileSeries = [
70
+ { key: "p95", name: "p95" },
71
+ { key: "p50", name: "p50" },
72
+ { key: "p99", name: "p99", dashed: true },
73
+ ];
74
+
75
+ export const AllVariants: Story = () => {
76
+ const [isolated, setIsolated] = useState<string | null>(null);
77
+ const hiddenPercentiles = new Set(
78
+ isolated == null ? [] : percentileSeries.map((entry) => entry.key).filter((key) => key !== isolated),
79
+ );
80
+
81
+ return (
82
+ <div className="mx-auto max-w-[1600px] p-8">
83
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3">
84
+ <ChartCard
85
+ palette="cyan"
86
+ accent="left"
87
+ kicker="Last 24h"
88
+ title="Sessions"
89
+ description="Full-width · left accent"
90
+ className="md:col-span-2 xl:col-span-3"
91
+ >
92
+ <LineChart
93
+ data={compare}
94
+ index="t"
95
+ series={[
96
+ { key: "claude", name: "Claude" },
97
+ { key: "chatgpt", name: "ChatGPT" },
98
+ ]}
99
+ lastValueLabel
100
+ legend
101
+ valueFormatter={nf}
102
+ />
103
+ </ChartCard>
104
+
105
+ <ChartCard palette="magenta" kicker="Last 24h" title="Output tokens" description="Single series · value flags">
106
+ <Stat value="1.4M" unit="tokens" delta={{ value: 8.1, direction: "up" }} sparkline={tokensSpark} />
107
+ <LineChart data={tokens} index="t" series={[{ key: "v", name: "tokens" }]} valueFlags valueFormatter={fmtK} />
108
+ </ChartCard>
109
+
110
+ <ChartCard
111
+ palette="magenta"
112
+ kicker="Last 24h"
113
+ title="Request latency"
114
+ description="p50 vs p95 · SLA band + peak"
115
+ >
116
+ <Stat value="240ms" unit="p50 · current" delta={{ value: 4.2, direction: "down", invert: true }} />
117
+ <LineChart
118
+ data={latency}
119
+ index="t"
120
+ series={[
121
+ { key: "p50", name: "p50" },
122
+ { key: "p95", name: "p95", dashed: true, color: "#9b5de5" },
123
+ ]}
124
+ referenceLine={{ y: 1000, label: "SLA 1s", band: true }}
125
+ markers={[{ x: latencyPeak.t, y: latencyPeak.p95, label: "peak", color: "#9b5de5" }]}
126
+ legend
127
+ valueFormatter={ms}
128
+ />
129
+ </ChartCard>
130
+
131
+ <ChartCard
132
+ palette="magenta"
133
+ kicker="Last 24h"
134
+ title="Percentiles"
135
+ description="Interactive legend · click to isolate"
136
+ >
137
+ <LineChart
138
+ data={latency}
139
+ index="t"
140
+ series={percentileSeries}
141
+ dots
142
+ legend
143
+ legendAlign="center"
144
+ lastValueLabel
145
+ hiddenSeries={hiddenPercentiles}
146
+ onLegendItemClick={(key) => setIsolated((current) => (current === key ? null : key))}
147
+ valueFormatter={ms}
148
+ />
149
+ </ChartCard>
150
+
151
+ <ChartCard palette="cyan" kicker="Last 24h" title="Sessions" description="Claude vs ChatGPT · last values">
152
+ <LineChart
153
+ data={compare}
154
+ index="t"
155
+ series={[
156
+ { key: "claude", name: "Claude" },
157
+ { key: "chatgpt", name: "ChatGPT" },
158
+ ]}
159
+ lastValueLabel
160
+ legend
161
+ valueFormatter={nf}
162
+ />
163
+ </ChartCard>
164
+
165
+ <ChartCard palette="cyan" kicker="Last 24h" title="Throughput" description="Dots · stepped curve">
166
+ <LineChart
167
+ data={tokens}
168
+ index="t"
169
+ series={[{ key: "v", name: "tokens" }]}
170
+ curve="step"
171
+ dots
172
+ valueFormatter={fmtK}
173
+ />
174
+ </ChartCard>
175
+
176
+ <ChartCard palette="magenta" kicker="State" title="Loading" description="Mono spinner placeholder">
177
+ <LineChart data={[]} index="t" series={[{ key: "v", name: "tokens" }]} loading />
178
+ </ChartCard>
179
+
180
+ <ChartCard palette="magenta" kicker="State" title="Empty" description="No data in range">
181
+ <LineChart data={[]} index="t" series={[{ key: "v", name: "tokens" }]} />
182
+ </ChartCard>
183
+ </div>
144
184
  </div>
145
- </div>
146
- );
185
+ );
186
+ };
@@ -23,10 +23,7 @@ import {
23
23
  SidebarTrigger,
24
24
  } from "../components/sidebar";
25
25
 
26
- /**
27
- * Wraps stories so `fixed` inside SidebarProvider becomes `absolute`
28
- * relative to this container (via `transform: scale(1)` trick).
29
- */
26
+ /** `transform: scale(1)` makes the SidebarProvider's `fixed` elements position relative to this frame. */
30
27
  function StoryFrame({ children, height = 600 }: { children: ReactNode; height?: number }) {
31
28
  return (
32
29
  <div
@@ -4,7 +4,6 @@ import { Skeleton } from "../components/skeleton";
4
4
 
5
5
  export const AllVariants: Story = () => (
6
6
  <div className="flex flex-col gap-8">
7
- {/* Shape variants */}
8
7
  <div className="flex flex-col gap-1.5">
9
8
  <p className="type-text-xs font-medium text-subtle-foreground">Rectangle (default)</p>
10
9
  <div className="flex flex-col gap-2">
@@ -23,7 +22,6 @@ export const AllVariants: Story = () => (
23
22
  </div>
24
23
  </div>
25
24
 
26
- {/* Common compositions */}
27
25
  <div className="flex flex-col gap-1.5">
28
26
  <p className="type-text-xs font-medium text-subtle-foreground">Card placeholder</p>
29
27
  <div className="flex flex-col gap-3 rounded-lg border border-border p-4">
@@ -88,7 +88,6 @@ const PAGE_SIZE = 3;
88
88
 
89
89
  export const AllVariants: Story = () => (
90
90
  <div className="flex flex-col gap-8 p-6 bg-background max-w-4xl">
91
- {/* Text-only table */}
92
91
  <div className="flex flex-col gap-1.5">
93
92
  <p className="type-text-xs font-medium text-subtle-foreground">Text cells</p>
94
93
  <Table>
@@ -115,7 +114,6 @@ export const AllVariants: Story = () => (
115
114
  </Table>
116
115
  </div>
117
116
 
118
- {/* Avatar cells + checkbox */}
119
117
  <div className="flex flex-col gap-1.5">
120
118
  <p className="type-text-xs font-medium text-subtle-foreground">Avatar cells + checkbox</p>
121
119
  <Table>
@@ -148,7 +146,6 @@ export const AllVariants: Story = () => (
148
146
  </Table>
149
147
  </div>
150
148
 
151
- {/* With footer */}
152
149
  <div className="flex flex-col gap-1.5">
153
150
  <p className="type-text-xs font-medium text-subtle-foreground">With caption + footer</p>
154
151
  <Table>
@@ -178,7 +175,6 @@ export const AllVariants: Story = () => (
178
175
  </Table>
179
176
  </div>
180
177
 
181
- {/* Selected row state */}
182
178
  <div className="flex flex-col gap-1.5">
183
179
  <p className="type-text-xs font-medium text-subtle-foreground">Selected row state</p>
184
180
  <Table>
@@ -201,7 +197,6 @@ export const AllVariants: Story = () => (
201
197
  </Table>
202
198
  </div>
203
199
 
204
- {/* Paginated table */}
205
200
  <PaginatedTableExample />
206
201
  </div>
207
202
  );
@@ -42,9 +42,6 @@ export const AllVariants: Story = () => {
42
42
 
43
43
  return (
44
44
  <div className="flex flex-col gap-10 p-8">
45
- {/* ─── Navigation tabs ─────────────────────────────────────── */}
46
-
47
- {/* Horizontal + line (default) */}
48
45
  <div>
49
46
  <p className={SECTION_HEADER}>Nav — horizontal, variant="line" (default)</p>
50
47
  <div className="mt-4">
@@ -61,7 +58,6 @@ export const AllVariants: Story = () => {
61
58
  </div>
62
59
  </div>
63
60
 
64
- {/* Horizontal + pill */}
65
61
  <div>
66
62
  <p className={SECTION_HEADER}>Nav — horizontal, variant="pill"</p>
67
63
  <div className="mt-4">
@@ -78,7 +74,6 @@ export const AllVariants: Story = () => {
78
74
  </div>
79
75
  </div>
80
76
 
81
- {/* Vertical + pill (default) */}
82
77
  <div>
83
78
  <p className={SECTION_HEADER}>Nav — vertical, variant="pill" (default)</p>
84
79
  <div className="mt-4 flex gap-6">
@@ -99,9 +94,6 @@ export const AllVariants: Story = () => {
99
94
  </div>
100
95
  </div>
101
96
 
102
- {/* ─── Tabs (state-based) ────────────────────────────── */}
103
-
104
- {/* Tabs — line */}
105
97
  <div>
106
98
  <p className={SECTION_HEADER}>Tabs — line variant</p>
107
99
  <Tabs defaultValue="all" className="mt-4">
@@ -118,7 +110,6 @@ export const AllVariants: Story = () => {
118
110
  </Tabs>
119
111
  </div>
120
112
 
121
- {/* Tabs — default (horizontal) */}
122
113
  <div>
123
114
  <p className={SECTION_HEADER}>Tabs — default variant (horizontal)</p>
124
115
  <Tabs defaultValue="all" className="mt-4">
@@ -135,7 +126,6 @@ export const AllVariants: Story = () => {
135
126
  </Tabs>
136
127
  </div>
137
128
 
138
- {/* Tabs — default (vertical) */}
139
129
  <div>
140
130
  <p className={SECTION_HEADER}>Tabs — default variant (vertical)</p>
141
131
  <Tabs defaultValue="overview" orientation="vertical" className="mt-4">
@@ -150,7 +140,6 @@ export const AllVariants: Story = () => {
150
140
  </Tabs>
151
141
  </div>
152
142
 
153
- {/* Tabs — disabled */}
154
143
  <div>
155
144
  <p className={SECTION_HEADER}>Tabs — disabled trigger</p>
156
145
  <Tabs defaultValue="one" className="mt-4">