Files
shadcn-ui/apps/v4/registry/bases/base/examples/chart-example.tsx
Dominik K. 137b1c12b7 feat(ui): add support for phosphor icons (#9044)
* feat: add phosphor icons to base ui

* feat_ add phosphor to blocks

* feat: add phosphor to radix blocks

* feat: add phosphor to radix ui

* feat: add phosphor to radix example

* feat: add missing phosphor icons

* fix: rename broken icons

* chore: format files

* fix: add missing phosphor icons

* chore: build registry

---------

Co-authored-by: shadcn <m@shadcn.com>
2025-12-17 21:36:46 +04:00

576 lines
17 KiB
TypeScript

"use client"
import * as React from "react"
import {
Area,
AreaChart,
Bar,
BarChart,
CartesianGrid,
Label,
Line,
LineChart,
Pie,
PieChart,
PolarAngleAxis,
PolarGrid,
PolarRadiusAxis,
Radar,
RadarChart,
RadialBar,
RadialBarChart,
XAxis,
} from "recharts"
import {
Example,
ExampleWrapper,
} from "@/registry/bases/base/components/example"
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/registry/bases/base/ui/card"
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
type ChartConfig,
} from "@/registry/bases/base/ui/chart"
import { IconPlaceholder } from "@/app/(create)/components/icon-placeholder"
const areaChartData = [
{ month: "January", desktop: 186 },
{ month: "February", desktop: 305 },
{ month: "March", desktop: 237 },
{ month: "April", desktop: 73 },
{ month: "May", desktop: 209 },
{ month: "June", desktop: 214 },
]
const areaChartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
} satisfies ChartConfig
export default function ChartExample() {
return (
<ExampleWrapper>
<ChartAreaExample />
<ChartBarExample />
<ChartLineExample />
<ChartRadialExample />
<ChartRadarExample />
</ExampleWrapper>
)
}
function ChartAreaExample() {
return (
<Example title="Area Chart">
<Card className="w-full">
<CardHeader>
<CardTitle>Area Chart</CardTitle>
<CardDescription>
Showing total visitors for the last 6 months
</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={areaChartConfig}>
<AreaChart
accessibilityLayer
data={areaChartData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent indicator="line" />}
/>
<Area
dataKey="desktop"
type="natural"
fill="var(--color-desktop)"
fillOpacity={0.4}
stroke="var(--color-desktop)"
/>
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div className="flex w-full items-start gap-2">
<div className="grid gap-2">
<div className="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</div>
</div>
</CardFooter>
</Card>
</Example>
)
}
const barChartData = [
{ month: "January", desktop: 186, mobile: 80 },
{ month: "February", desktop: 305, mobile: 200 },
{ month: "March", desktop: 237, mobile: 120 },
{ month: "April", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "June", desktop: 214, mobile: 140 },
]
const barChartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--chart-2)",
},
} satisfies ChartConfig
function ChartBarExample() {
return (
<Example title="Bar Chart">
<Card className="w-full">
<CardHeader>
<CardTitle>Bar Chart - Multiple</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={barChartConfig}>
<BarChart accessibilityLayer data={barChartData}>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
tickMargin={10}
axisLine={false}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent indicator="dashed" />}
/>
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter className="flex-col items-start gap-2">
<div className="flex gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>
</Example>
)
}
const lineChartData = [
{ month: "January", desktop: 186, mobile: 80 },
{ month: "February", desktop: 305, mobile: 200 },
{ month: "March", desktop: 237, mobile: 120 },
{ month: "April", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "June", desktop: 214, mobile: 140 },
]
const lineChartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--chart-2)",
},
} satisfies ChartConfig
function ChartLineExample() {
return (
<Example title="Line Chart">
<Card className="w-full">
<CardHeader>
<CardTitle>Line Chart - Multiple</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={lineChartConfig}>
<LineChart
accessibilityLayer
data={lineChartData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="month"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => value.slice(0, 3)}
/>
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
<Line
dataKey="desktop"
type="monotone"
stroke="var(--color-desktop)"
strokeWidth={2}
dot={false}
/>
<Line
dataKey="mobile"
type="monotone"
stroke="var(--color-mobile)"
strokeWidth={2}
dot={false}
/>
</LineChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div className="flex w-full items-start gap-2">
<div className="grid gap-2">
<div className="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground flex items-center gap-2 leading-none">
Showing total visitors for the last 6 months
</div>
</div>
</div>
</CardFooter>
</Card>
</Example>
)
}
const pieChartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
{ browser: "firefox", visitors: 287, fill: "var(--color-firefox)" },
{ browser: "edge", visitors: 173, fill: "var(--color-edge)" },
{ browser: "other", visitors: 190, fill: "var(--color-other)" },
]
const pieChartConfig = {
visitors: {
label: "Visitors",
},
chrome: {
label: "Chrome",
color: "var(--chart-1)",
},
safari: {
label: "Safari",
color: "var(--chart-2)",
},
firefox: {
label: "Firefox",
color: "var(--chart-3)",
},
edge: {
label: "Edge",
color: "var(--chart-4)",
},
other: {
label: "Other",
color: "var(--chart-5)",
},
} satisfies ChartConfig
function ChartPieExample() {
const totalVisitors = React.useMemo(() => {
return pieChartData.reduce((acc, curr) => acc + curr.visitors, 0)
}, [])
return (
<Example title="Pie Chart">
<Card className="w-full">
<CardHeader className="items-center pb-0">
<CardTitle>Pie Chart - Donut with Text</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent className="flex-1 pb-0">
<ChartContainer
config={pieChartConfig}
className="mx-auto aspect-square max-h-[250px]"
>
<PieChart>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel />}
/>
<Pie
data={pieChartData}
dataKey="visitors"
nameKey="browser"
innerRadius={60}
strokeWidth={5}
>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-3xl font-bold"
>
{totalVisitors.toLocaleString()}
</tspan>
<tspan
x={viewBox.cx}
y={(viewBox.cy || 0) + 24}
className="fill-muted-foreground"
>
Visitors
</tspan>
</text>
)
}
}}
/>
</Pie>
</PieChart>
</ChartContainer>
</CardContent>
<CardFooter className="flex-col gap-2">
<div className="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>
</Example>
)
}
const radarChartData = [
{ month: "January", desktop: 186, mobile: 80 },
{ month: "February", desktop: 305, mobile: 200 },
{ month: "March", desktop: 237, mobile: 120 },
{ month: "April", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "June", desktop: 214, mobile: 140 },
]
const radarChartConfig = {
desktop: {
label: "Desktop",
color: "var(--chart-1)",
},
mobile: {
label: "Mobile",
color: "var(--chart-2)",
},
} satisfies ChartConfig
function ChartRadarExample() {
return (
<Example title="Radar Chart">
<Card className="w-full">
<CardHeader className="items-center pb-4">
<CardTitle>Radar Chart - Multiple</CardTitle>
<CardDescription>
Showing total visitors for the last 6 months
</CardDescription>
</CardHeader>
<CardContent className="pb-0">
<ChartContainer
config={radarChartConfig}
className="mx-auto aspect-square max-h-[250px]"
>
<RadarChart data={radarChartData}>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent indicator="line" />}
/>
<PolarAngleAxis dataKey="month" />
<PolarGrid />
<Radar
dataKey="desktop"
fill="var(--color-desktop)"
fillOpacity={0.6}
/>
<Radar dataKey="mobile" fill="var(--color-mobile)" />
</RadarChart>
</ChartContainer>
</CardContent>
<CardFooter className="flex-col gap-2">
<div className="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground flex items-center gap-2 leading-none">
January - June 2024
</div>
</CardFooter>
</Card>
</Example>
)
}
const radialChartData = [
{ browser: "safari", visitors: 1260, fill: "var(--color-safari)" },
]
const radialChartConfig = {
visitors: {
label: "Visitors",
},
safari: {
label: "Safari",
color: "var(--chart-2)",
},
} satisfies ChartConfig
function ChartRadialExample() {
return (
<Example title="Radial Chart">
<Card className="w-full">
<CardHeader>
<CardTitle>Radial Chart - Shape</CardTitle>
<CardDescription>January - June 2024</CardDescription>
</CardHeader>
<CardContent className="flex-1 pb-0">
<ChartContainer
config={radialChartConfig}
className="mx-auto aspect-square max-h-[210px]"
>
<RadialBarChart
data={radialChartData}
endAngle={100}
innerRadius={80}
outerRadius={140}
>
<PolarGrid
gridType="circle"
radialLines={false}
stroke="none"
className="first:fill-muted last:fill-background"
polarRadius={[86, 74]}
/>
<RadialBar dataKey="visitors" background />
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-4xl font-bold"
>
{radialChartData[0].visitors.toLocaleString()}
</tspan>
<tspan
x={viewBox.cx}
y={(viewBox.cy || 0) + 24}
className="fill-muted-foreground"
>
Visitors
</tspan>
</text>
)
}
}}
/>
</PolarRadiusAxis>
</RadialBarChart>
</ChartContainer>
</CardContent>
<CardFooter className="flex-col gap-2">
<div className="flex items-center gap-2 leading-none font-medium">
Trending up by 5.2% this month{" "}
<IconPlaceholder
lucide="TrendingUpIcon"
tabler="IconTrendingUp"
hugeicons="ChartUpIcon"
phosphor="TrendUpIcon"
className="size-4"
/>
</div>
<div className="text-muted-foreground leading-none">
Showing total visitors for the last 6 months
</div>
</CardFooter>
</Card>
</Example>
)
}