# Blueprint: Generated Dashboard

> An analytics assistant answers with a dashboard card. KPIs count up through `data-blueprint-count`, chart bars grow from even placeholders into their real heights through `--blueprint-progress`, and table rows fill in cell by cell. Drag the scrubber to take it apart and put it back.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/blueprint-dashboard-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/blueprint-dashboard-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/blueprint-dashboard-demo-light-e245516a1d3c5333.png
- Registry item: https://keyframeui.com/r/blueprint-dashboard-demo.json
- Categories: layout, scroll, motion
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/blueprint-dashboard-demo.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: `https://keyframeui.com/r/blueprint.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/blueprint#blueprint-dashboard-demo

## Files

### `registry/demos/blueprint-dashboard-demo.tsx`

```tsx
import { Blueprint } from "@/components/ui/blueprint";

const regions = [
  { name: "North America", short: "NA", revenue: 1.64, change: "+14.2%" },
  { name: "Europe", short: "EU", revenue: 1.38, change: "+9.8%" },
  { name: "Asia Pacific", short: "APAC", revenue: 1.02, change: "+21.5%" },
  { name: "Latin America", short: "LATAM", revenue: 0.49, change: "+6.1%" },
  { name: "Middle East & Africa", short: "MEA", revenue: 0.29, change: "+3.4%" },
];

const kpis = [
  { label: "Revenue", value: "$4.82M" },
  { label: "vs. Q2", value: "+12.4%" },
  { label: "Orders", value: "18,240" },
];

const top = Math.max(...regions.map((r) => r.revenue));
// In the wireframe every bar stands at the same placeholder height, then grows or settles
// into its real one as it builds. --blueprint-progress runs 0–1 on each block while it builds.
const SKELETON_BAR = 0.42;
const barStyle = (revenue: number) => {
  const height = revenue / top;
  const from = SKELETON_BAR / height;
  return {
    height: `${height * 100}%`,
    scale: `1 calc(${from} + ${1 - from} * var(--blueprint-progress, 1))`,
  };
};

export function BlueprintDashboardDemo() {
  return (
    <div className="w-full max-w-2xl rounded-2xl border border-zinc-200 bg-zinc-50 p-4 text-zinc-900 sm:p-5 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100">
      <div className="flex justify-end">
        <p className="rounded-2xl rounded-br-md bg-zinc-900 px-3.5 py-2 text-sm text-white dark:bg-white dark:text-zinc-900">
          Revenue by region, last quarter
        </p>
      </div>
      <p className="mt-4 mb-3 flex items-center gap-2 text-xs text-zinc-500">
        <svg viewBox="0 0 16 16" fill="currentColor" className="size-3.5 text-indigo-500" aria-hidden>
          <path d="M8 1.5 9.6 6.4 14.5 8l-4.9 1.6L8 14.5 6.4 9.6 1.5 8l4.9-1.6L8 1.5Z" />
        </svg>
        Built from 4 queries on orders and accounts
      </p>

      <Blueprint play="auto" scrubber duration={{ build: 6, hold: 3 }}>
        <div
          data-blueprint="box"
          data-blueprint-label="Card"
          className="rounded-xl border border-zinc-200 bg-white p-4 shadow-sm sm:p-5 dark:border-zinc-800 dark:bg-zinc-900"
        >
          <div className="flex items-start justify-between gap-4">
            <div>
              <h3 data-blueprint className="text-base font-semibold tracking-tight">
                Revenue by region
              </h3>
              <p data-blueprint className="mt-0.5 text-xs text-zinc-500">
                Q3 2026 · Jul 1 – Sep 30
              </p>
            </div>
            <button
              data-blueprint
              type="button"
              className="rounded-md border border-zinc-200 px-2.5 py-1 text-xs font-medium dark:border-zinc-700"
            >
              Export
            </button>
          </div>

          <div className="mt-4 grid grid-cols-3 gap-2 sm:gap-3">
            {kpis.map((kpi) => (
              <div key={kpi.label} className="rounded-lg bg-zinc-50 px-3 py-2.5 dark:bg-zinc-800/60">
                <p data-blueprint className="text-xs text-zinc-500">
                  {kpi.label}
                </p>
                <p
                  data-blueprint
                  data-blueprint-count
                  className="mt-0.5 text-lg font-semibold tracking-tight tabular-nums sm:text-xl"
                >
                  {kpi.value}
                </p>
              </div>
            ))}
          </div>

          <div className="mt-5 flex h-32 items-end gap-3 border-b border-zinc-200 px-1 sm:gap-5 dark:border-zinc-800">
            {regions.map((region, i) => (
              <div
                key={region.short}
                data-blueprint="box"
                className={
                  i === 0
                    ? "flex-1 origin-bottom rounded-t-md bg-indigo-500 dark:bg-indigo-400"
                    : "flex-1 origin-bottom rounded-t-md bg-indigo-500/45 dark:bg-indigo-400/45"
                }
                style={barStyle(region.revenue)}
              />
            ))}
          </div>
          <div data-blueprint="text" className="mt-1.5 flex gap-3 px-1 text-[11px] text-zinc-500 sm:gap-5">
            {regions.map((region) => (
              <span key={region.short} className="flex-1 text-center">
                {region.short}
              </span>
            ))}
          </div>

          <div className="mt-5 text-sm">
            <div
              data-blueprint="text"
              className="grid grid-cols-[1fr_5rem_4rem] gap-x-4 pb-2 text-[11px] font-medium tracking-wide text-zinc-500 uppercase"
            >
              <span>Region</span>
              <span className="text-right">Revenue</span>
              <span className="text-right">Change</span>
            </div>
            {regions.map((region) => (
              <div
                key={region.short}
                data-blueprint="text"
                data-blueprint-count
                className="grid grid-cols-[1fr_5rem_4rem] gap-x-4 border-t border-zinc-100 py-2 tabular-nums dark:border-zinc-800"
              >
                <span className="truncate">{region.name}</span>
                <span className="text-right">${region.revenue.toFixed(2)}M</span>
                <span className="text-right text-emerald-600 dark:text-emerald-400">{region.change}</span>
              </div>
            ))}
          </div>
        </div>
      </Blueprint>
    </div>
  );
}
```
