# Live Dashboard

> Studio status board with editable CONTENT projects.

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

- Page, with a live preview: https://shadcn.exchange/r/atroui/live-dashboard
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/atroui/live-dashboard-light-e45d0c702c3d36b6.png
- Registry item: https://www.atroui.com/r/live-dashboard.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.atroui.com/r/live-dashboard.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`
- Registry items: `@atroui/utils`, `@atroui/fade-in`

## Files

### `registry/default/blocks/live-dashboard.tsx`

```tsx
"use client"

import { Activity, Circle } from "lucide-react"
import { useEffect, useState } from "react"

import { FadeIn } from "@/components/ui/fade-in"
import { cn } from "@/lib/utils"

type Status = "active" | "shipping" | "paused"

/** Edit CONTENT.projects for your studio board. */
const CONTENT = {
  footerNote:
    "Anonymized snapshots shared with client permission. Slots: 2 of 3 filled.",
  projects: [
    {
      id: "p1",
      name: "Billing dashboard",
      client: "Acme",
      status: "active" as Status,
      milestone: "Checkout polish",
      progress: 72,
      lastUpdate: "Shipped invoice PDF export",
      service: "MVP sprint",
      public: true,
    },
    {
      id: "p2",
      name: "Ops AI inbox",
      client: "Northwind",
      status: "shipping" as Status,
      milestone: "Prompt evals",
      progress: 88,
      lastUpdate: "Cut false positives 30%",
      service: "AI feature",
      public: true,
    },
  ],
}

const STATUS_COLORS: Record<Status, string> = {
  active: "border-emerald-500/40 text-emerald-400",
  shipping: "border-sky-500/40 text-sky-400",
  paused: "border-amber-500/40 text-amber-400",
}

const STATUS_LABELS: Record<Status, string> = {
  active: "Active",
  shipping: "Shipping",
  paused: "Paused",
}

export function LiveDashboard() {
  const [now, setNow] = useState<Date | null>(null)

  useEffect(() => {
    setNow(new Date())
    const id = setInterval(() => setNow(new Date()), 60_000)
    return () => clearInterval(id)
  }, [])

  const publicProjects = CONTENT.projects.filter((p) => p.public)

  return (
    <div>
      <div className="ms-shell-pad flex items-center justify-between border-b border-border-subtle py-4">
        <div className="flex items-center gap-2">
          <span className="relative flex h-2 w-2">
            <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-75" />
            <span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-500" />
          </span>
          <span className="text-xs font-medium text-muted-foreground">
            Studio live · {publicProjects.length} active project
            {publicProjects.length === 1 ? "" : "s"}
          </span>
        </div>
        {now ? (
          <span className="ds-mono-label flex items-center gap-1.5">
            <Activity className="size-3" />
            Updated{" "}
            {now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
          </span>
        ) : null}
      </div>

      <ul className="divide-y divide-border-subtle">
        {publicProjects.map((project, i) => (
          <li key={project.id}>
            <FadeIn delay={i * 0.05}>
              <article className="grid grid-cols-1 items-start gap-3 px-6 py-5 md:grid-cols-12 md:gap-4 md:px-8 md:py-6">
                <span className="font-mono text-[11px] tabular-nums text-muted-foreground md:col-span-1">
                  {String(i + 1).padStart(2, "0")}
                </span>
                <div className="md:col-span-4">
                  <div className="flex flex-wrap items-center gap-2">
                    <h3 className="text-sm font-medium text-foreground">
                      {project.name}
                    </h3>
                    <span
                      className={cn(
                        "shrink-0 border px-2 py-0.5 text-[10px] font-medium",
                        STATUS_COLORS[project.status]
                      )}
                    >
                      {STATUS_LABELS[project.status]}
                    </span>
                  </div>
                  <p className="mt-0.5 text-xs text-muted-foreground">
                    {project.client}
                  </p>
                </div>
                <div className="md:col-span-4">
                  <div className="flex items-center justify-between text-[10px] text-muted-foreground">
                    <span>{project.milestone}</span>
                    <span>{project.progress}%</span>
                  </div>
                  <div className="mt-1.5 h-1 overflow-hidden border border-border-subtle bg-muted">
                    <div
                      className="h-full bg-brand transition-all duration-700"
                      style={{ width: `${project.progress}%` }}
                    />
                  </div>
                  <p className="mt-2 text-xs leading-relaxed text-muted-foreground">
                    <Circle className="mr-1 inline size-2 fill-emerald-500 text-emerald-500" />
                    {project.lastUpdate}
                  </p>
                </div>
                <p className="text-[11px] text-muted-foreground md:col-span-3 md:text-right">
                  {project.service}
                </p>
              </article>
            </FadeIn>
          </li>
        ))}
      </ul>

      <p className="ms-shell-pad py-4 text-[11px] text-muted-foreground">
        {CONTENT.footerNote}
      </p>
    </div>
  )
}
```
