# Weekly Goal Radial Chart

> Narrow card with a radial ring showing progress toward a weekly listening goal, minutes in the center, the remaining track visible and a footer note. Client component on recharts 3.8.

A shadcn/ui block from the [@01orbital](https://01orbital.dev/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/01orbital/radial-chart-01).

- Page, with a live preview: https://shadcn.exchange/r/01orbital/radial-chart-01
- Screenshot: https://shadcn.exchange/shot/01orbital/radial-chart-01/light.png
- Registry item: https://01orbital.dev/r/radial-chart-01.json
- Categories: charts
- Listed: 2026-11-01, source last changed 2026-11-01

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/01orbital/radial-chart-01.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `recharts`
- Registry items: `card`, `@01orbital/chart`

## Files

### `blocks/charts/radial-chart-01/index.tsx`

```tsx
"use client"

import {
  Label,
  PolarAngleAxis,
  PolarRadiusAxis,
  RadialBar,
  RadialBarChart,
} from "recharts"

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

// The copy: change text here, not in the markup.
const COPY = {
  title: "Weekly goal",
  description: "October 12 to 18",
  unit: "of 600 minutes",
  note: "138 minutes to go, about 20 a day.",
} as const

const GOAL = 600
const LISTENED = [{ goal: "week", minutes: 462, fill: "var(--color-minutes)" }]

const CHART_CONFIG = {
  minutes: { label: "Minutes", color: "var(--chart-2)" },
} satisfies ChartConfig

export default function RadialChart01() {
  return (
    <Card className="mx-auto w-full max-w-xs">
      <CardHeader>
        <CardTitle>
          <h2>{COPY.title}</h2>
        </CardTitle>
        <CardDescription>{COPY.description}</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={CHART_CONFIG}
          className="mx-auto aspect-square max-h-64"
        >
          <RadialBarChart
            data={LISTENED}
            startAngle={90}
            endAngle={-270}
            innerRadius={86}
            outerRadius={112}
          >
            {/* The goal sets the full turn; the track shows what is left. */}
            <PolarAngleAxis type="number" domain={[0, GOAL]} tick={false} />
            <RadialBar dataKey="minutes" background cornerRadius={12} />
            <PolarRadiusAxis tick={false} tickLine={false} axisLine={false}>
              <Label
                content={({ viewBox }) => {
                  if (!viewBox || !("cx" in viewBox)) return null
                  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-medium tabular-nums"
                      >
                        {LISTENED[0].minutes}
                      </tspan>
                      <tspan
                        x={viewBox.cx}
                        y={(viewBox.cy ?? 0) + 28}
                        className="fill-muted-foreground"
                      >
                        {COPY.unit}
                      </tspan>
                    </text>
                  )
                }}
              />
            </PolarRadiusAxis>
          </RadialBarChart>
        </ChartContainer>
      </CardContent>
      <CardFooter className="justify-center text-sm text-muted-foreground">
        <p>{COPY.note}</p>
      </CardFooter>
    </Card>
  )
}
```
