NEW
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
Learn more
Skip to content
Docs

Ring Chart

A simple ring-chart chart as seen in iOS apps

Loading...

Installation

CLI

pnpm dlx shadcn@latest add https://animata.design/r/graphs/ring-chart.json

Manual

Run the following command

It will create a new file called ring-chart.tsx inside the components/animata/graphs directory.

mkdir -p components/animata/graphs && touch components/animata/graphs/ring-chart.tsx

Paste the code

Open the newly created file and paste the following code:

import DonutChart from "@/animata/graphs/donut-chart";
import { cn } from "@/lib/utils";
 
type RingItem = {
  progress: number;
  className?: string;
  trackClassName: string;
  progressClassName: string;
};
 
interface RingChartProps {
  /**
   * Size of the smallest ring
   * @default 96
   */
  size?: number;
 
  /**
   * Gap between rings
   * @default 4
   */
  gap?: number;
 
  /**
   * Width of the ring
   * @default 20
   */
  width?: number;
 
  /**
   * Additional class name of the container
   */
  className?: string;
 
  rings: RingItem[];
}
 
const sampleRings: RingItem[] = [
  {
    progress: 10,
    trackClassName: "text-rose-600/10",
    progressClassName: "text-rose-600",
  },
  {
    progress: 60,
    trackClassName: "text-lime-500/20",
    progressClassName: "text-lime-500",
  },
  {
    progress: 40,
    trackClassName: "text-teal-400/30",
    progressClassName: "text-teal-400",
  },
];
 
const calculateRingSize = ({
  size = 96,
  width = 20,
  gap = 4,
  index,
  total,
}: Pick<RingChartProps, "gap" | "size" | "width"> & {
  index: number;
  total: number;
}) => {
  const position = total - index;
  // Size of the smallest ring + ring width on 2 side + gap on 2 side
  // offset by the position.
  return size + position * width * 2 + gap * position * 2;
};
 
export default function RingChart({
  size = 96,
  gap = 4,
  width = 20,
  className,
  rings = sampleRings,
}: RingChartProps) {
  const totalWidth = calculateRingSize({
    size,
    width,
    gap,
    index: 0,
    total: rings.length,
  });
 
  return (
    <div
      className={cn("relative flex items-center justify-center rounded-3xl bg-zinc-950", className)}
      style={{
        minWidth: totalWidth + gap * rings.length * 4,
        minHeight: totalWidth + gap * rings.length * 4,
      }}
    >
      {rings.map((ring, index) => {
        const ringSize = calculateRingSize({
          size,
          width,
          gap,
          index,
          total: rings.length,
        });
        return (
          <DonutChart
            key={`ring_${index}`}
            size={ringSize}
            {...ring}
            progressWidth={width}
            circleWidth={width}
            className={cn("absolute", ring.className)}
          />
        );
      })}
    </div>
  );
}

Credits

Built by hari