7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

shadcn chartsで実現する統一されたチャートの実装

7
Last updated at Posted at 2025-12-16

shadcn/ui とは

shadcn/uiとは美しいデフォルトスタイルを備えたアクセシブルなUIコンポーネントのセットであり、独自のコンポーネントライブラリを構築するためのコード配布プラットフォームです。

従来のUIライブラリでは、パッケージをインストールしてコンポーネントを使い、必要に応じてスタイルを上書きしたりラップしたりしてカスタマイズしますが、この手法では独自デザインへの対応が難しくなります。

それに対してshadcnで提供されるコンポーネントはすべて手元で編集可能な「オープンコード」になっているのが特徴で、従来のUIライブラリでの課題を解決するものになっています。

shadcn chart とは

基本的な考え方は前述したオープンコードで提供されるコンポーネントであることは変わりません。チャート自体はRechartsを使うことが前提に作られており、shadcnではアプリケーションのテーマの統一、アクセシビリティの向上、デザインシステムとしての拡張性をもたらしてくれます。

プロジェクトの作成

Next.jsのアプリケーションをベースにshadcn chartを組み込むので、まずはNext.jsをインストールします。

pnpm create next-app@latest my-shadcn-charts --yes

次にshadcn chartsをインストールします。

pnpm dlx shadcn@latest add chart

rechartsのAreaChartをベースにshadcnのコンポーネントを追加したいので、適当に必要なデータを生成して表示させてみます。

"use client";

import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts";

const chartData = [
  { month: "January", desktop: 186, mobile: 120, tablet: 90 },
  { month: "February", desktop: 305, mobile: 200, tablet: 150 },
  { month: "March", desktop: 237, mobile: 180, tablet: 130 },
  { month: "April", desktop: 73, mobile: 95, tablet: 60 },
  { month: "May", desktop: 209, mobile: 160, tablet: 120 },
  { month: "June", desktop: 214, mobile: 170, tablet: 140 },
  { month: "July", desktop: 250, mobile: 190, tablet: 160 },
  { month: "August", desktop: 280, mobile: 210, tablet: 180 },
  { month: "September", desktop: 230, mobile: 175, tablet: 135 },
  { month: "October", desktop: 190, mobile: 150, tablet: 120 },
  { month: "November", desktop: 220, mobile: 170, tablet: 140 },
  { month: "December", desktop: 260, mobile: 200, tablet: 160 },
];

export default function Charts() {
  return (
    <div className="flex justify-center items-center h-screen">
      <AreaChart accessibilityLayer data={chartData} width={800} height={400}>
        <CartesianGrid />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickFormatter={(value) => value.slice(0, 3)}
        />
        <YAxis tickLine={false} axisLine={false} tickMargin={8} tickCount={3} />
        <Area dataKey="desktop" type="natural" fillOpacity={0.4} />
        <Area dataKey="mobile" type="natural" fillOpacity={0.4} />
        <Area dataKey="tablet" type="natural" fillOpacity={0.4} />
      </AreaChart>
    </div>
  );
}

現状こんな感じです。

image.png

shadcn chartの利用

<AreaChart /><ChartContainer />でラップすることにより、shadcnのスタイルが適応されます。Recharts自体をラップしたコンポーネントを使用しているわけではないので、チャート部分はRechartsのプリミティブな機能をそのまま備えています。

chartConfigでラベルやカラーを設定することができ、こうすることでダークテーマの対応が楽になり、アプリケーション全体のスタイルに一貫性が生まれます。CSS変数に関してはshadcn chartをインストールした時点でglobal.cssに定義されます。

import { ChartContainer, type ChartConfig } from "@/components/ui/chart";

...

// chartDateと対応させる
const chartConfig = {
  desktop: {
    label: "Desktop",
    color: "var(--chart-1)",
  },
  tablet: {
    label: "Tablet",
    color: "var(--chart-2)",
  },
  mobile: {
    label: "Mobile",
    color: "var(--chart-3)",
  },
} satisfies ChartConfig;

export default function Charts() {
  return (
    <div className="flex justify-center items-center h-screen">
      <ChartContainer config={chartConfig} className="h-[400px] w-[800px]">
        <AreaChart accessibilityLayer data={chartData} width={800} height={400}>
          <CartesianGrid />
          <XAxis
            dataKey="month"
            tickLine={false}
            axisLine={false}
            tickFormatter={(value) => value.slice(0, 3)}
          />
          <YAxis
            tickLine={false}
            axisLine={false}
            tickMargin={8}
            tickCount={3}
          />
          <Area
            dataKey="desktop"
            type="natural"
            fill="var(--color-desktop)"
            fillOpacity={0.4}
            stroke="var(--color-desktop)"
          />
          <Area
            dataKey="mobile"
            type="natural"
            fill="var(--color-mobile)"
            fillOpacity={0.4}
            stroke="var(--color-mobile)"
          />
          <Area
            dataKey="tablet"
            type="natural"
            fill="var(--color-tablet)"
            fillOpacity={0.4}
            stroke="var(--color-tablet)"
          />
        </AreaChart>
      </ChartContainer>
    </div>
  );
}

image.png

ダークテーマ

image.png

色々追加してみる

shadcnでチャートをインストールするとカードコンポーネントも一緒にインストールされ、チャートをラップすることでより見栄えを整えることができます。
下記はツールチップの追加、カードとヘッダーとフッターの追加をした例です。

import {
  ChartContainer,
  type ChartConfig,
  ChartTooltip,
  ChartTooltipContent,
  ChartLegend,
  ChartLegendContent,
} from "@/components/ui/chart";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";

...

export default function Charts() {
  return (
    <div className="flex justify-center items-center h-screen">
      <Card>
        <CardHeader>
          <CardTitle className="text-lg font-semibold">Heading</CardTitle>
          <CardDescription>description</CardDescription>
        </CardHeader>
        <CardContent>
          <ChartContainer
            config={chartConfig}
            className="w-[600px] min-h-[200px]"
          >
            <AreaChart
              accessibilityLayer
              data={chartData}
              margin={{
                left: -20,
                right: 12,
              }}
            >
              <CartesianGrid />
              <XAxis
                dataKey="month"
                tickLine={false}
                axisLine={false}
                tickFormatter={(value) => value.slice(0, 3)}
                fontSize={14}
              />
              <YAxis
                tickLine={false}
                axisLine={false}
                tickMargin={8}
                tickCount={3}
                fontSize={14}
              />
              <Area
                dataKey="desktop"
                type="natural"
                fill="var(--color-desktop)"
                fillOpacity={0.4}
                stroke="var(--color-desktop)"
              />
              <Area
                dataKey="mobile"
                type="natural"
                fill="var(--color-mobile)"
                fillOpacity={0.4}
                stroke="var(--color-mobile)"
              />
              <Area
                dataKey="tablet"
                type="natural"
                fill="var(--color-tablet)"
                fillOpacity={0.4}
                stroke="var(--color-tablet)"
              />
              <ChartTooltip content={<ChartTooltipContent />} />
              <ChartLegend content={<ChartLegendContent />} />
            </AreaChart>
          </ChartContainer>
        </CardContent>
        <CardFooter>
          <div className="flex w-full items-start gap-2 text-sm">
            <div className="grid gap-2">
              <div className="flex items-center gap-2 leading-none font-medium">
                footer text
              </div>
            </div>
          </div>
        </CardFooter>
      </Card>
    </div>
  );
}

一貫性のあるスタイルがあたり、見やすくなりました。

image.png

最後に

今回はチャートに焦点をあてましたが、ボタン、フォーム、タブ、テーブルなど、他にも多くのコンポーネントが提供されています。質の高いコンポーネントをスピード感をもって開発できるのと学習コストも低いので気軽に導入できる点もいいと思います。

ドキュメント

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?