sonance-brand-mcp 1.2.5 → 1.3.1

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 (90) hide show
  1. package/dist/assets/components/alert-dialog.stories.tsx +142 -0
  2. package/dist/assets/components/alert-dialog.tsx +142 -0
  3. package/dist/assets/components/aspect-ratio.stories.tsx +67 -0
  4. package/dist/assets/components/aspect-ratio.tsx +8 -0
  5. package/dist/assets/components/avatar.tsx +64 -20
  6. package/dist/assets/components/carousel.stories.tsx +158 -0
  7. package/dist/assets/components/carousel.tsx +262 -0
  8. package/dist/assets/components/chart.stories.tsx +376 -0
  9. package/dist/assets/components/chart.tsx +384 -0
  10. package/dist/assets/components/checkbox.tsx +12 -2
  11. package/dist/assets/components/code.tsx +22 -20
  12. package/dist/assets/components/collapsible.stories.tsx +128 -0
  13. package/dist/assets/components/collapsible.tsx +10 -0
  14. package/dist/assets/components/command.stories.tsx +183 -0
  15. package/dist/assets/components/command.tsx +170 -0
  16. package/dist/assets/components/context-menu.stories.tsx +159 -0
  17. package/dist/assets/components/context-menu.tsx +218 -0
  18. package/dist/assets/components/divider.tsx +38 -35
  19. package/dist/assets/components/dropdown-menu.tsx +217 -0
  20. package/dist/assets/components/hover-card.stories.tsx +113 -0
  21. package/dist/assets/components/hover-card.tsx +35 -0
  22. package/dist/assets/components/kbd.tsx +6 -6
  23. package/dist/assets/components/menubar.stories.tsx +208 -0
  24. package/dist/assets/components/menubar.tsx +251 -0
  25. package/dist/assets/components/navigation-menu.stories.tsx +237 -0
  26. package/dist/assets/components/navigation-menu.tsx +135 -0
  27. package/dist/assets/components/resizable.stories.tsx +197 -0
  28. package/dist/assets/components/resizable.tsx +47 -0
  29. package/dist/assets/components/scroll-area.stories.tsx +123 -0
  30. package/dist/assets/components/scroll-area.tsx +48 -0
  31. package/dist/assets/components/scroll-shadow.tsx +29 -7
  32. package/dist/assets/components/separator.tsx +32 -0
  33. package/dist/assets/components/sheet.tsx +141 -0
  34. package/dist/assets/components/sidebar.stories.tsx +351 -0
  35. package/dist/assets/components/sidebar.tsx +760 -0
  36. package/dist/assets/components/toggle-group.stories.tsx +153 -0
  37. package/dist/assets/components/toggle-group.tsx +61 -0
  38. package/dist/assets/components/toggle.stories.tsx +77 -0
  39. package/dist/assets/components/toggle.tsx +46 -0
  40. package/dist/assets/components/tooltip.tsx +23 -90
  41. package/dist/assets/globals.css +30 -0
  42. package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
  43. package/dist/assets/logos/Sonance logo dark mode.png +0 -0
  44. package/dist/assets/logos/Sonance logo light mode.png +0 -0
  45. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
  46. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
  47. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
  48. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
  49. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
  50. package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
  51. package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
  52. package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
  53. package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
  54. package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
  55. package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
  56. package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
  57. package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
  58. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
  59. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
  60. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
  61. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
  62. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
  63. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
  64. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
  65. package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
  66. package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
  67. package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
  68. package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
  69. package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
  70. package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
  71. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
  72. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
  73. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
  74. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
  75. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
  76. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
  77. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
  78. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
  79. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
  80. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
  81. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
  82. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
  83. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
  84. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
  85. package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
  86. package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
  87. package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
  88. package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
  89. package/dist/index.js +278 -7
  90. package/package.json +1 -1
@@ -0,0 +1,262 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import useEmblaCarousel, {
5
+ type UseEmblaCarouselType,
6
+ } from "embla-carousel-react";
7
+ import { ArrowLeft, ArrowRight } from "lucide-react";
8
+ import { cn } from "@/lib/utils";
9
+ import { Button } from "@/components/ui/button";
10
+
11
+ type CarouselApi = UseEmblaCarouselType[1];
12
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
13
+ type CarouselOptions = UseCarouselParameters[0];
14
+ type CarouselPlugin = UseCarouselParameters[1];
15
+
16
+ type CarouselProps = {
17
+ opts?: CarouselOptions;
18
+ plugins?: CarouselPlugin;
19
+ orientation?: "horizontal" | "vertical";
20
+ setApi?: (api: CarouselApi) => void;
21
+ };
22
+
23
+ type CarouselContextProps = {
24
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0];
25
+ api: ReturnType<typeof useEmblaCarousel>[1];
26
+ scrollPrev: () => void;
27
+ scrollNext: () => void;
28
+ canScrollPrev: boolean;
29
+ canScrollNext: boolean;
30
+ } & CarouselProps;
31
+
32
+ const CarouselContext = React.createContext<CarouselContextProps | null>(null);
33
+
34
+ function useCarousel() {
35
+ const context = React.useContext(CarouselContext);
36
+
37
+ if (!context) {
38
+ throw new Error("useCarousel must be used within a <Carousel />");
39
+ }
40
+
41
+ return context;
42
+ }
43
+
44
+ const Carousel = React.forwardRef<
45
+ HTMLDivElement,
46
+ React.HTMLAttributes<HTMLDivElement> & CarouselProps
47
+ >(
48
+ (
49
+ {
50
+ orientation = "horizontal",
51
+ opts,
52
+ setApi,
53
+ plugins,
54
+ className,
55
+ children,
56
+ ...props
57
+ },
58
+ ref
59
+ ) => {
60
+ const [carouselRef, api] = useEmblaCarousel(
61
+ {
62
+ ...opts,
63
+ axis: orientation === "horizontal" ? "x" : "y",
64
+ },
65
+ plugins
66
+ );
67
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false);
68
+ const [canScrollNext, setCanScrollNext] = React.useState(false);
69
+
70
+ const onSelect = React.useCallback((api: CarouselApi) => {
71
+ if (!api) {
72
+ return;
73
+ }
74
+
75
+ setCanScrollPrev(api.canScrollPrev());
76
+ setCanScrollNext(api.canScrollNext());
77
+ }, []);
78
+
79
+ const scrollPrev = React.useCallback(() => {
80
+ api?.scrollPrev();
81
+ }, [api]);
82
+
83
+ const scrollNext = React.useCallback(() => {
84
+ api?.scrollNext();
85
+ }, [api]);
86
+
87
+ const handleKeyDown = React.useCallback(
88
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
89
+ if (event.key === "ArrowLeft") {
90
+ event.preventDefault();
91
+ scrollPrev();
92
+ } else if (event.key === "ArrowRight") {
93
+ event.preventDefault();
94
+ scrollNext();
95
+ }
96
+ },
97
+ [scrollPrev, scrollNext]
98
+ );
99
+
100
+ React.useEffect(() => {
101
+ if (!api || !setApi) {
102
+ return;
103
+ }
104
+
105
+ setApi(api);
106
+ }, [api, setApi]);
107
+
108
+ React.useEffect(() => {
109
+ if (!api) {
110
+ return;
111
+ }
112
+
113
+ onSelect(api);
114
+ api.on("reInit", onSelect);
115
+ api.on("select", onSelect);
116
+
117
+ return () => {
118
+ api?.off("select", onSelect);
119
+ };
120
+ }, [api, onSelect]);
121
+
122
+ return (
123
+ <CarouselContext.Provider
124
+ value={{
125
+ carouselRef,
126
+ api: api,
127
+ opts,
128
+ orientation:
129
+ orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
130
+ scrollPrev,
131
+ scrollNext,
132
+ canScrollPrev,
133
+ canScrollNext,
134
+ }}
135
+ >
136
+ <div
137
+ ref={ref}
138
+ onKeyDownCapture={handleKeyDown}
139
+ className={cn("relative", className)}
140
+ role="region"
141
+ aria-roledescription="carousel"
142
+ {...props}
143
+ >
144
+ {children}
145
+ </div>
146
+ </CarouselContext.Provider>
147
+ );
148
+ }
149
+ );
150
+ Carousel.displayName = "Carousel";
151
+
152
+ const CarouselContent = React.forwardRef<
153
+ HTMLDivElement,
154
+ React.HTMLAttributes<HTMLDivElement>
155
+ >(({ className, ...props }, ref) => {
156
+ const { carouselRef, orientation } = useCarousel();
157
+
158
+ return (
159
+ <div ref={carouselRef} className="overflow-hidden">
160
+ <div
161
+ ref={ref}
162
+ className={cn(
163
+ "flex",
164
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
165
+ className
166
+ )}
167
+ {...props}
168
+ />
169
+ </div>
170
+ );
171
+ });
172
+ CarouselContent.displayName = "CarouselContent";
173
+
174
+ const CarouselItem = React.forwardRef<
175
+ HTMLDivElement,
176
+ React.HTMLAttributes<HTMLDivElement>
177
+ >(({ className, ...props }, ref) => {
178
+ const { orientation } = useCarousel();
179
+
180
+ return (
181
+ <div
182
+ ref={ref}
183
+ role="group"
184
+ aria-roledescription="slide"
185
+ className={cn(
186
+ "min-w-0 shrink-0 grow-0 basis-full",
187
+ orientation === "horizontal" ? "pl-4" : "pt-4",
188
+ className
189
+ )}
190
+ {...props}
191
+ />
192
+ );
193
+ });
194
+ CarouselItem.displayName = "CarouselItem";
195
+
196
+ const CarouselPrevious = React.forwardRef<
197
+ HTMLButtonElement,
198
+ React.ButtonHTMLAttributes<HTMLButtonElement>
199
+ >(({ className, ...props }, ref) => {
200
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel();
201
+
202
+ return (
203
+ <Button
204
+ ref={ref}
205
+ variant="secondary"
206
+ size="sm"
207
+ className={cn(
208
+ "absolute h-8 w-8 rounded-full p-0",
209
+ orientation === "horizontal"
210
+ ? "-left-12 top-1/2 -translate-y-1/2"
211
+ : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
212
+ className
213
+ )}
214
+ disabled={!canScrollPrev}
215
+ onClick={scrollPrev}
216
+ {...props}
217
+ >
218
+ <ArrowLeft className="h-4 w-4" />
219
+ <span className="sr-only">Previous slide</span>
220
+ </Button>
221
+ );
222
+ });
223
+ CarouselPrevious.displayName = "CarouselPrevious";
224
+
225
+ const CarouselNext = React.forwardRef<
226
+ HTMLButtonElement,
227
+ React.ButtonHTMLAttributes<HTMLButtonElement>
228
+ >(({ className, ...props }, ref) => {
229
+ const { orientation, scrollNext, canScrollNext } = useCarousel();
230
+
231
+ return (
232
+ <Button
233
+ ref={ref}
234
+ variant="secondary"
235
+ size="sm"
236
+ className={cn(
237
+ "absolute h-8 w-8 rounded-full p-0",
238
+ orientation === "horizontal"
239
+ ? "-right-12 top-1/2 -translate-y-1/2"
240
+ : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
241
+ className
242
+ )}
243
+ disabled={!canScrollNext}
244
+ onClick={scrollNext}
245
+ {...props}
246
+ >
247
+ <ArrowRight className="h-4 w-4" />
248
+ <span className="sr-only">Next slide</span>
249
+ </Button>
250
+ );
251
+ });
252
+ CarouselNext.displayName = "CarouselNext";
253
+
254
+ export {
255
+ type CarouselApi,
256
+ Carousel,
257
+ CarouselContent,
258
+ CarouselItem,
259
+ CarouselPrevious,
260
+ CarouselNext,
261
+ };
262
+
@@ -0,0 +1,376 @@
1
+ "use client";
2
+
3
+ import type { Meta, StoryObj } from "@storybook/react";
4
+ import {
5
+ Area,
6
+ AreaChart,
7
+ Bar,
8
+ BarChart,
9
+ CartesianGrid,
10
+ Line,
11
+ LineChart,
12
+ Pie,
13
+ PieChart,
14
+ XAxis,
15
+ YAxis,
16
+ } from "recharts";
17
+ import {
18
+ ChartConfig,
19
+ ChartContainer,
20
+ ChartLegend,
21
+ ChartLegendContent,
22
+ ChartTooltip,
23
+ ChartTooltipContent,
24
+ } from "./chart";
25
+
26
+ const meta: Meta<typeof ChartContainer> = {
27
+ title: "Components/Data Display/Chart",
28
+ component: ChartContainer,
29
+ parameters: {
30
+ layout: "centered",
31
+ },
32
+ tags: ["autodocs"],
33
+ };
34
+
35
+ export default meta;
36
+ type Story = StoryObj<typeof ChartContainer>;
37
+
38
+ // Sample data
39
+ const lineData = [
40
+ { month: "January", desktop: 186, mobile: 80 },
41
+ { month: "February", desktop: 305, mobile: 200 },
42
+ { month: "March", desktop: 237, mobile: 120 },
43
+ { month: "April", desktop: 73, mobile: 190 },
44
+ { month: "May", desktop: 209, mobile: 130 },
45
+ { month: "June", desktop: 214, mobile: 140 },
46
+ ];
47
+
48
+ const lineChartConfig = {
49
+ desktop: {
50
+ label: "Desktop",
51
+ color: "hsl(var(--primary))",
52
+ },
53
+ mobile: {
54
+ label: "Mobile",
55
+ color: "hsl(var(--accent))",
56
+ },
57
+ } satisfies ChartConfig;
58
+
59
+ export const LineChartExample: Story = {
60
+ render: () => (
61
+ <div className="w-[600px]">
62
+ <ChartContainer config={lineChartConfig}>
63
+ <LineChart
64
+ accessibilityLayer
65
+ data={lineData}
66
+ margin={{
67
+ left: 12,
68
+ right: 12,
69
+ }}
70
+ >
71
+ <CartesianGrid vertical={false} />
72
+ <XAxis
73
+ dataKey="month"
74
+ tickLine={false}
75
+ axisLine={false}
76
+ tickMargin={8}
77
+ tickFormatter={(value) => value.slice(0, 3)}
78
+ />
79
+ <ChartTooltip cursor={false} content={<ChartTooltipContent />} />
80
+ <Line
81
+ dataKey="desktop"
82
+ type="monotone"
83
+ stroke="var(--color-desktop)"
84
+ strokeWidth={2}
85
+ dot={false}
86
+ />
87
+ <Line
88
+ dataKey="mobile"
89
+ type="monotone"
90
+ stroke="var(--color-mobile)"
91
+ strokeWidth={2}
92
+ dot={false}
93
+ />
94
+ </LineChart>
95
+ </ChartContainer>
96
+ </div>
97
+ ),
98
+ };
99
+
100
+ const barData = [
101
+ { month: "January", desktop: 186 },
102
+ { month: "February", desktop: 305 },
103
+ { month: "March", desktop: 237 },
104
+ { month: "April", desktop: 73 },
105
+ { month: "May", desktop: 209 },
106
+ { month: "June", desktop: 214 },
107
+ ];
108
+
109
+ const barChartConfig = {
110
+ desktop: {
111
+ label: "Desktop",
112
+ color: "hsl(var(--primary))",
113
+ },
114
+ } satisfies ChartConfig;
115
+
116
+ export const BarChartExample: Story = {
117
+ render: () => (
118
+ <div className="w-[600px]">
119
+ <ChartContainer config={barChartConfig}>
120
+ <BarChart accessibilityLayer data={barData}>
121
+ <CartesianGrid vertical={false} />
122
+ <XAxis
123
+ dataKey="month"
124
+ tickLine={false}
125
+ tickMargin={10}
126
+ axisLine={false}
127
+ tickFormatter={(value) => value.slice(0, 3)}
128
+ />
129
+ <ChartTooltip
130
+ cursor={false}
131
+ content={<ChartTooltipContent hideLabel />}
132
+ />
133
+ <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
134
+ </BarChart>
135
+ </ChartContainer>
136
+ </div>
137
+ ),
138
+ };
139
+
140
+ const areaData = [
141
+ { month: "January", desktop: 186, mobile: 80 },
142
+ { month: "February", desktop: 305, mobile: 200 },
143
+ { month: "March", desktop: 237, mobile: 120 },
144
+ { month: "April", desktop: 73, mobile: 190 },
145
+ { month: "May", desktop: 209, mobile: 130 },
146
+ { month: "June", desktop: 214, mobile: 140 },
147
+ ];
148
+
149
+ const areaChartConfig = {
150
+ desktop: {
151
+ label: "Desktop",
152
+ color: "hsl(var(--primary))",
153
+ },
154
+ mobile: {
155
+ label: "Mobile",
156
+ color: "hsl(var(--accent))",
157
+ },
158
+ } satisfies ChartConfig;
159
+
160
+ export const AreaChartExample: Story = {
161
+ render: () => (
162
+ <div className="w-[600px]">
163
+ <ChartContainer config={areaChartConfig}>
164
+ <AreaChart
165
+ accessibilityLayer
166
+ data={areaData}
167
+ margin={{
168
+ left: 12,
169
+ right: 12,
170
+ }}
171
+ >
172
+ <CartesianGrid vertical={false} />
173
+ <XAxis
174
+ dataKey="month"
175
+ tickLine={false}
176
+ axisLine={false}
177
+ tickMargin={8}
178
+ tickFormatter={(value) => value.slice(0, 3)}
179
+ />
180
+ <ChartTooltip cursor={false} content={<ChartTooltipContent />} />
181
+ <defs>
182
+ <linearGradient id="fillDesktop" x1="0" y1="0" x2="0" y2="1">
183
+ <stop
184
+ offset="5%"
185
+ stopColor="var(--color-desktop)"
186
+ stopOpacity={0.8}
187
+ />
188
+ <stop
189
+ offset="95%"
190
+ stopColor="var(--color-desktop)"
191
+ stopOpacity={0.1}
192
+ />
193
+ </linearGradient>
194
+ <linearGradient id="fillMobile" x1="0" y1="0" x2="0" y2="1">
195
+ <stop
196
+ offset="5%"
197
+ stopColor="var(--color-mobile)"
198
+ stopOpacity={0.8}
199
+ />
200
+ <stop
201
+ offset="95%"
202
+ stopColor="var(--color-mobile)"
203
+ stopOpacity={0.1}
204
+ />
205
+ </linearGradient>
206
+ </defs>
207
+ <Area
208
+ dataKey="mobile"
209
+ type="natural"
210
+ fill="url(#fillMobile)"
211
+ fillOpacity={0.4}
212
+ stroke="var(--color-mobile)"
213
+ stackId="a"
214
+ />
215
+ <Area
216
+ dataKey="desktop"
217
+ type="natural"
218
+ fill="url(#fillDesktop)"
219
+ fillOpacity={0.4}
220
+ stroke="var(--color-desktop)"
221
+ stackId="a"
222
+ />
223
+ </AreaChart>
224
+ </ChartContainer>
225
+ </div>
226
+ ),
227
+ };
228
+
229
+ const pieData = [
230
+ { browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
231
+ { browser: "safari", visitors: 200, fill: "var(--color-safari)" },
232
+ { browser: "firefox", visitors: 287, fill: "var(--color-firefox)" },
233
+ { browser: "edge", visitors: 173, fill: "var(--color-edge)" },
234
+ { browser: "other", visitors: 190, fill: "var(--color-other)" },
235
+ ];
236
+
237
+ const pieChartConfig = {
238
+ visitors: {
239
+ label: "Visitors",
240
+ },
241
+ chrome: {
242
+ label: "Chrome",
243
+ color: "hsl(var(--primary))",
244
+ },
245
+ safari: {
246
+ label: "Safari",
247
+ color: "hsl(var(--accent))",
248
+ },
249
+ firefox: {
250
+ label: "Firefox",
251
+ color: "#ef4444",
252
+ },
253
+ edge: {
254
+ label: "Edge",
255
+ color: "#f97316",
256
+ },
257
+ other: {
258
+ label: "Other",
259
+ color: "#a855f7",
260
+ },
261
+ } satisfies ChartConfig;
262
+
263
+ export const PieChartExample: Story = {
264
+ render: () => (
265
+ <div className="w-[400px]">
266
+ <ChartContainer
267
+ config={pieChartConfig}
268
+ className="mx-auto aspect-square max-h-[300px]"
269
+ >
270
+ <PieChart>
271
+ <ChartTooltip
272
+ cursor={false}
273
+ content={<ChartTooltipContent hideLabel />}
274
+ />
275
+ <Pie
276
+ data={pieData}
277
+ dataKey="visitors"
278
+ nameKey="browser"
279
+ innerRadius={60}
280
+ strokeWidth={5}
281
+ />
282
+ </PieChart>
283
+ </ChartContainer>
284
+ </div>
285
+ ),
286
+ };
287
+
288
+ const salesData = [
289
+ { product: "Architectural", sales: 4000 },
290
+ { product: "Outdoor", sales: 3000 },
291
+ { product: "Invisible", sales: 2000 },
292
+ { product: "Subwoofers", sales: 2780 },
293
+ { product: "Amplifiers", sales: 1890 },
294
+ ];
295
+
296
+ const salesChartConfig = {
297
+ sales: {
298
+ label: "Sales",
299
+ color: "hsl(var(--primary))",
300
+ },
301
+ } satisfies ChartConfig;
302
+
303
+ export const HorizontalBarChart: Story = {
304
+ render: () => (
305
+ <div className="w-[600px]">
306
+ <ChartContainer config={salesChartConfig}>
307
+ <BarChart
308
+ accessibilityLayer
309
+ data={salesData}
310
+ layout="vertical"
311
+ margin={{
312
+ left: 20,
313
+ }}
314
+ >
315
+ <CartesianGrid horizontal={false} />
316
+ <YAxis
317
+ dataKey="product"
318
+ type="category"
319
+ tickLine={false}
320
+ tickMargin={10}
321
+ axisLine={false}
322
+ />
323
+ <XAxis dataKey="sales" type="number" hide />
324
+ <ChartTooltip
325
+ cursor={false}
326
+ content={<ChartTooltipContent hideLabel />}
327
+ />
328
+ <Bar dataKey="sales" fill="var(--color-sales)" radius={4} />
329
+ </BarChart>
330
+ </ChartContainer>
331
+ </div>
332
+ ),
333
+ };
334
+
335
+ const monthlyRevenueData = [
336
+ { month: "Jan", revenue: 12000, target: 10000 },
337
+ { month: "Feb", revenue: 15000, target: 12000 },
338
+ { month: "Mar", revenue: 18000, target: 15000 },
339
+ { month: "Apr", revenue: 14000, target: 16000 },
340
+ { month: "May", revenue: 22000, target: 18000 },
341
+ { month: "Jun", revenue: 28000, target: 20000 },
342
+ ];
343
+
344
+ const revenueChartConfig = {
345
+ revenue: {
346
+ label: "Revenue",
347
+ color: "hsl(var(--primary))",
348
+ },
349
+ target: {
350
+ label: "Target",
351
+ color: "hsl(var(--accent))",
352
+ },
353
+ } satisfies ChartConfig;
354
+
355
+ export const WithLegend: Story = {
356
+ render: () => (
357
+ <div className="w-[600px]">
358
+ <ChartContainer config={revenueChartConfig}>
359
+ <BarChart accessibilityLayer data={monthlyRevenueData}>
360
+ <CartesianGrid vertical={false} />
361
+ <XAxis
362
+ dataKey="month"
363
+ tickLine={false}
364
+ tickMargin={10}
365
+ axisLine={false}
366
+ />
367
+ <ChartTooltip content={<ChartTooltipContent />} />
368
+ <ChartLegend content={<ChartLegendContent payload={[]} />} />
369
+ <Bar dataKey="revenue" fill="var(--color-revenue)" radius={4} />
370
+ <Bar dataKey="target" fill="var(--color-target)" radius={4} />
371
+ </BarChart>
372
+ </ChartContainer>
373
+ </div>
374
+ ),
375
+ };
376
+