# Stats Usage Dashboard

> A stats usage dashboard block.

A shadcn/ui block from the [@blocks-so](https://blocks.so) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/blocks-so/stats-12).

- Page, with a live preview: https://shadcn.exchange/r/blocks-so/stats-12
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/blocks-so/stats-12-light-83254a85aa2fa458.png
- Registry item: https://blocks.so/r/stats-12.json
- Categories: stats
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://blocks.so/r/stats-12.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: `button`, `card`, `chart`

## Files

### `content/components/stats/stats-12.tsx`

```tsx
'use client';

import { Cell, Pie, PieChart } from 'recharts';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { type ChartConfig, ChartContainer } from '@/components/ui/chart';

interface UsageItem {
  name: string;
  current: string;
  limit: string;
  percentage: number;
  href?: string;
}

const usageData: UsageItem[] = [
  { name: 'ISR Reads', current: '358K', limit: '1M', percentage: 35.8 },
  { name: 'Edge Requests', current: '317K', limit: '1M', percentage: 31.7 },
  {
    name: 'Fast Origin Transfer',
    current: '3.07 GB',
    limit: '10 GB',
    percentage: 30.7,
  },
  {
    name: 'Speed Insights Data Points',
    current: '791',
    limit: '10K',
    percentage: 7.9,
  },
  {
    name: 'Fast Data Transfer',
    current: '4.98 GB',
    limit: '100 GB',
    percentage: 5.0,
  },
  {
    name: 'Function Duration',
    current: '3.1 GB-Hrs',
    limit: '100 GB-Hrs',
    percentage: 3.1,
  },
  {
    name: 'Web Analytics Events',
    current: '1.3K',
    limit: '50K',
    percentage: 2.6,
  },
  { name: 'ISR Writes', current: '4.8K', limit: '200K', percentage: 2.4 },
  {
    name: 'Function Invocations',
    current: '19K',
    limit: '1M',
    percentage: 1.9,
  },
  {
    name: 'Image Optimization - Cache Reads',
    current: '4.3K',
    limit: '300K',
    percentage: 1.4,
  },
];

const chartConfig = {
  used: {
    label: 'Used',
    color: 'hsl(var(--primary))',
  },
  remaining: {
    label: 'Remaining',
    color: 'hsl(var(--muted))',
  },
} satisfies ChartConfig;

function DonutChart({ percentage }: { percentage: number }) {
  const backgroundData = [{ name: 'background', value: 100, fill: '#E5E7EB' }];
  const foregroundData = [
    {
      name: 'used',
      value: Math.max(0, Math.min(100, Number(percentage))),
      fill: '#3B82F6',
    },
    {
      name: 'empty',
      value: 100 - Math.max(0, Math.min(100, Number(percentage))),
      fill: 'transparent',
    },
  ];

  return (
    <ChartContainer
      className="aspect-square h-6 w-6 shrink-0"
      config={chartConfig}
    >
      <PieChart>
        <Pie
          cx="50%"
          cy="50%"
          data={backgroundData}
          dataKey="value"
          innerRadius={6}
          isAnimationActive={false}
          nameKey="name"
          outerRadius={10}
        >
          {backgroundData.map((entry, index) => (
            <Cell fill={entry.fill} key={`bg-cell-${index}`} />
          ))}
        </Pie>
        <Pie
          cx="50%"
          cy="50%"
          data={foregroundData}
          dataKey="value"
          endAngle={-270}
          innerRadius={6}
          nameKey="name"
          outerRadius={10}
          startAngle={90}
        >
          {foregroundData.map((entry, index) => (
            <Cell fill={entry.fill} key={`fg-cell-${index}`} />
          ))}
        </Pie>
      </PieChart>
    </ChartContainer>
  );
}

export default function Stats12() {
  return (
    <Card className="w-full max-w-md gap-3 py-5 shadow-2xs">
      <CardHeader className="px-5">
        <div className="flex items-center justify-between">
          <div className="flex flex-col">
            <h3 className="text-balance font-medium text-sm">Last 30 days</h3>
            <p className="text-pretty font-medium text-muted-foreground text-xs">
              Updated just now
            </p>
          </div>
          <Button className="h-6 font-medium text-xs" size="sm">
            Upgrade
          </Button>
        </div>
      </CardHeader>

      <CardContent className="px-3 pt-0">
        <div className="space-y-0">
          {usageData.map((item, index) => (
            <div
              className={`flex items-center gap-3 rounded-sm p-2 transition-colors hover:bg-muted/50 ${
                index % 2 === 1 ? 'bg-muted/20' : ''
              }`}
              key={item.name}
            >
              <DonutChart percentage={item.percentage} />
              <span className="flex-1 truncate text-sm leading-4">
                {item.name}
              </span>
              <span className="font-medium text-muted-foreground text-xs tabular-nums tracking-tighter">
                {item.current} /{' '}
                <span className="text-foreground">{item.limit}</span>
              </span>
            </div>
          ))}
        </div>
      </CardContent>
    </Card>
  );
}
```
