본문으로 건너뛰기
언어

Chartstandard

recharts 위에 색 설정과 툴팁·범례 모양을 얹은 차트 틀(chart)입니다. shadcn base-nova 의 원본을 그대로 담은 아이템입니다. 차트 종류(막대, 선 등)는 recharts 를 그대로 씁니다.

설치

pnpm
pnpm dlx shadcn@4.23.0 add @uikit/chart

의존 아이템card

Default

chart-example.tsx
"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 "@/components/example"import {  Card,  CardContent,  CardDescription,  CardFooter,  CardHeader,  CardTitle,} from "@/components/ui/card"import {  ChartContainer,  ChartTooltip,  ChartTooltipContent,  type ChartConfig,} from "@/components/ui/chart"import { TrendingUpIcon } from "lucide-react"
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 />      <ChartPieExample />      <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{" "}                <TrendingUpIcon className="size-4" />              </div>              <div className="flex items-center gap-2 leading-none text-muted-foreground">                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{" "}            <TrendingUpIcon className="size-4" />          </div>          <div className="leading-none text-muted-foreground">            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{" "}                <TrendingUpIcon className="size-4" />              </div>              <div className="flex items-center gap-2 leading-none text-muted-foreground">                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{" "}            <TrendingUpIcon className="size-4" />          </div>          <div className="leading-none text-muted-foreground">            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{" "}            <TrendingUpIcon className="size-4" />          </div>          <div className="flex items-center gap-2 leading-none text-muted-foreground">            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={64}              outerRadius={94}            >              <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{" "}            <TrendingUpIcon className="size-4" />          </div>          <div className="leading-none text-muted-foreground">            Showing total visitors for the last 6 months          </div>        </CardFooter>      </Card>    </Example>  )}