# Stats with Segmented Progress

> A stats with segmented progress block.

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

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

## Install

```bash
npx shadcn@latest add https://blocks.so/r/stats-13.json
```

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

## Dependencies

- Registry items: `card`

## Files

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

```tsx
'use client';

import { Card, CardContent } from '@/components/ui/card';
import { cn } from '@/lib/utils';

interface Props {
  title?: string;
  used?: number;
  total?: number;
  usedLabel?: string;
  totalLabel?: string;
  segments?: {
    label: string;
    value: number;
    color: string;
  }[];
  className?: string;
}

const defaultSegments: NonNullable<Props['segments']> = [
  { label: 'Documents', value: 2400, color: 'bg-blue-500' },
  { label: 'Photos', value: 1800, color: 'bg-emerald-500' },
  { label: 'Videos', value: 3200, color: 'bg-amber-500' },
  { label: 'Music', value: 900, color: 'bg-purple-500' },
];

export default function Stats13({
  title = 'Using Storage',
  used = 8300,
  total = 15,
  usedLabel = 'MB',
  totalLabel = 'GB',
  segments = defaultSegments,
  className,
}: Props) {
  const totalValue = total * 1000;
  const freeValue = totalValue - used;

  return (
    <Card className={cn('w-full max-w-4xl shadow-sm', className)}>
      <CardContent className="py-0">
        <p className="mb-4 text-pretty text-base text-muted-foreground">
          {title}{' '}
          <span className="font-semibold text-foreground tabular-nums">
            {used.toLocaleString(undefined, {
              minimumFractionDigits: 0,
              maximumFractionDigits: 2,
            })}{' '}
            {usedLabel}
          </span>{' '}
          of {total} {totalLabel}
        </p>

        <div className="mb-4 flex h-2.5 w-full overflow-hidden rounded-full bg-muted">
          {segments.map((segment) => {
            const percentage = (segment.value / totalValue) * 100;
            return (
              <div
                aria-label={segment.label}
                aria-valuemax={totalValue}
                aria-valuemin={0}
                aria-valuenow={segment.value}
                className={cn('h-full', segment.color)}
                key={segment.label}
                role="progressbar"
                style={{ width: `${percentage}%` }}
              />
            );
          })}
        </div>

        <div className="flex flex-wrap items-center gap-x-8 gap-y-2">
          {segments.map((segment) => (
            <div className="flex items-center gap-2" key={segment.label}>
              <span
                aria-hidden="true"
                className={cn('size-3 shrink-0 rounded', segment.color)}
              />
              <span className="text-muted-foreground text-sm">
                {segment.label}
              </span>
              <span className="text-muted-foreground text-sm tabular-nums">
                {Math.round(segment.value)}
                {usedLabel}
              </span>
            </div>
          ))}
          <div className="flex items-center gap-2">
            <span
              aria-hidden="true"
              className="size-3 shrink-0 rounded-sm bg-muted"
            />
            <span className="text-muted-foreground text-sm">Free</span>
            <span className="text-muted-foreground text-sm tabular-nums">
              {Math.round(freeValue)}
              {usedLabel}
            </span>
          </div>
        </div>
      </CardContent>
    </Card>
  );
}
```
