# Charts 11

> Charts 11 variant for block.

A shadcn/ui block from the [@uiable](https://uiable.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/uiable/block-charts-11).

- Page, with a live preview: https://shadcn.exchange/r/uiable/block-charts-11
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/uiable/block-charts-11-light-79802435a4ac7c25.png
- Registry item: https://uiable.com/r/block-charts-11.json
- Categories: charts
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://uiable.com/r/block-charts-11.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: `lucide-react`, `recharts`
- Registry items: `@uiable/button`, `@uiable/card`, `@uiable/chart`, `@uiable/dropdown-menu`

## Files

### `src/components/uiable/blocks/charts/charts-11/charts-11.tsx`

```tsx
"use client"

// shadcn
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import {
  ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

// third-party
import { Label, Pie, PieChart } from "recharts"

// assets
import {
  ArrowUpRight,
  BarChart3,
  BellRing,
  Download,
  MoreVertical,
  RefreshCcw,
  TrendingUp,
} from "lucide-react"

//  ------------------------------ | CHARTS 11 | ------------------------------  //

const chartConfig = {
  income: {
    label: "Income",
    color: "var(--color-teal-600)",
  },
  rent: {
    label: "Rent",
    color: "var(--color-amber-500)",
  },
  download: {
    label: "Download",
    color: "var(--color-blue-500)",
  },
  views: {
    label: "Views",
    color: "var(--color-teal-200)",
  },
} satisfies ChartConfig

type SegmentKey = "income" | "rent" | "download" | "views"

const chartData = [
  { key: "income", amount: 23876, change: 763.43, fill: "var(--color-income)" },
  { key: "rent", amount: 8420, change: 325.0, fill: "var(--color-rent)" },
  {
    key: "download",
    amount: 15760,
    change: 1284.0,
    fill: "var(--color-download)",
  },
  { key: "views", amount: 12480, change: 512.0, fill: "var(--color-views)" },
] satisfies { key: SegmentKey; amount: number; change: number; fill: string }[]

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  maximumFractionDigits: 0,
})

const compactCurrency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  notation: "compact",
  maximumFractionDigits: 1,
})

const incomeActions = [
  { label: "View breakdown", icon: BarChart3 },
  { label: "Export summary", icon: Download },
  { label: "Set alert", icon: BellRing },
  { label: "Refresh data", icon: RefreshCcw },
]

export default function Charts11() {
  const total = chartData.reduce((sum, item) => sum + item.amount, 0)

  return (
    <div className="w-full min-w-0">
      <Card className="mb-0 overflow-hidden rounded-2xl border-border/60 bg-card shadow-sm transition-shadow hover:shadow-md">
        <span
          aria-hidden
          className="pointer-events-none absolute -top-12 -left-10 size-32 rounded-full bg-teal-500 opacity-20 blur-3xl"
        />
        <CardContent className="flex flex-col gap-6 p-5 sm:p-6">
          {/* Header */}
          <div className="flex items-start justify-between gap-4">
            <h3 className="text-lg font-semibold tracking-tight text-foreground">
              Total Income
            </h3>
            <DropdownMenu>
              <DropdownMenuTrigger
                render={
                  <Button
                    variant="ghost"
                    size="icon-sm"
                    className="shrink-0 text-muted-foreground hover:bg-muted/70 hover:text-foreground"
                    aria-label="More options"
                  />
                }
              >
                <MoreVertical className="size-4" />
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end" className="w-52 p-1.5">
                {incomeActions.map(({ icon: Icon, label }) => (
                  <DropdownMenuItem
                    key={label}
                    className="gap-2 rounded-lg px-2 py-1.5 text-sm"
                    onSelect={(event) => event.preventDefault()}
                  >
                    <Icon className="size-4 text-muted-foreground" />
                    <span>{label}</span>
                  </DropdownMenuItem>
                ))}
                <DropdownMenuSeparator />
                <DropdownMenuItem
                  className="gap-2 rounded-lg px-2 py-1.5 text-sm"
                  onSelect={(event) => event.preventDefault()}
                >
                  <ArrowUpRight className="size-4 text-muted-foreground" />
                  <span>Compare periods</span>
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>

          {/* Donut chart */}
          <ChartContainer
            config={chartConfig}
            className="mx-auto aspect-square h-[240px] w-full min-w-0"
          >
            <PieChart>
              <ChartTooltip
                cursor={false}
                content={
                  <ChartTooltipContent
                    className="min-w-[10rem] gap-2 rounded-xl"
                    nameKey="key"
                    formatter={(value, name) => (
                      <div className="flex w-full items-center justify-between gap-4">
                        <span className="text-muted-foreground">
                          {chartConfig[name as SegmentKey]?.label}
                        </span>
                        <span className="font-medium text-foreground tabular-nums">
                          {currency.format(value as number)}
                        </span>
                      </div>
                    )}
                  />
                }
              />
              <Pie
                data={chartData}
                dataKey="amount"
                nameKey="key"
                innerRadius={72}
                outerRadius={100}
                paddingAngle={2}
                cornerRadius={6}
                strokeWidth={0}
              >
                <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 ?? 0) - 16}
                            className="fill-muted-foreground text-xs"
                          >
                            Total
                          </tspan>
                          <tspan
                            x={viewBox.cx}
                            y={(viewBox.cy ?? 0) + 10}
                            className="fill-foreground text-2xl font-semibold tabular-nums"
                          >
                            {compactCurrency.format(total)}
                          </tspan>
                        </text>
                      )
                    }
                    return null
                  }}
                />
              </Pie>
            </PieChart>
          </ChartContainer>

          {/* Legend cards */}
          <div className="grid grid-cols-1 gap-2.5 sm:grid-cols-2 sm:gap-3">
            {chartData.map((item) => (
              <Card
                key={item.key}
                className="group relative mb-0 flex flex-col gap-1.5 overflow-hidden rounded-xl border border-border/60 bg-muted/30 px-3.5 py-3 shadow-none transition-all hover:-translate-y-0.5 hover:bg-card hover:shadow-md"
              >
                {/* Subtle tinted glow */}
                <span
                  aria-hidden
                  className="pointer-events-none absolute -top-8 -right-6 size-20 rounded-full opacity-[0.07] blur-2xl transition-opacity group-hover:opacity-[0.16]"
                  style={{ backgroundColor: chartConfig[item.key].color }}
                />
                <span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
                  <span
                    className="size-2 rounded-full"
                    style={{ backgroundColor: chartConfig[item.key].color }}
                  />
                  {chartConfig[item.key].label}
                </span>
                <div className="flex flex-wrap items-baseline gap-x-2 gap-y-1">
                  <span className="text-lg font-semibold tracking-tight text-foreground tabular-nums sm:text-xl">
                    {currency.format(item.amount)}
                  </span>
                  <span className="inline-flex items-center gap-0.5 rounded-full bg-emerald-500/10 px-1.5 py-0.5 text-[11px] font-semibold text-emerald-600 ring-1 ring-emerald-500/15 ring-inset dark:text-emerald-400">
                    <TrendingUp className="size-3" />+
                    {currency.format(item.change)}
                  </span>
                </div>
              </Card>
            ))}
          </div>
        </CardContent>
      </Card>
    </div>
  )
}
```
