registry/blocks/app-shell.tsx
import {
Bell,
CircleGauge,
Folder,
LifeBuoy,
Rocket,
Search,
Settings,
Users,
} from "lucide-react";
import { cn } from "@/lib/utils";
const navigation = [
{ label: "Overview", icon: CircleGauge, active: true },
{ label: "Deployments", icon: Rocket, active: false },
{ label: "Projects", icon: Folder, active: false },
{ label: "Team", icon: Users, active: false },
{ label: "Settings", icon: Settings, active: false },
];
const deploys = [
{ project: "marketing-site", env: "production", status: "Ready", time: "2m ago" },
{ project: "api-gateway", env: "production", status: "Building", time: "6m ago" },
{ project: "docs", env: "preview", status: "Ready", time: "31m ago" },
];
export default function AppShell() {
return (
<section className="flex min-h-[640px] bg-background">
{/* Sidebar */}
<aside className="hidden w-56 shrink-0 flex-col border-r border-border/60 md:flex">
<div className="flex h-14 items-center gap-2 border-b border-border/60 px-4 font-semibold">
<span className="flex size-6 items-center justify-center rounded-md bg-foreground font-mono text-xs text-background">
A
</span>
Acme
</div>
<nav className="flex-1 space-y-0.5 p-2">
{navigation.map((item) => (
<a
key={item.label}
href="#"
aria-current={item.active ? "page" : undefined}
className={cn(
"flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors",
item.active
? "bg-accent font-medium"
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
)}
>
<item.icon className="size-4" />
{item.label}
</a>
))}
</nav>
<div className="border-t border-border/60 p-2">
<a
href="#"
className="flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
>
<LifeBuoy className="size-4" />
Support
</a>
</div>
</aside>
{/* Main */}
<div className="flex min-w-0 flex-1 flex-col">
{/* Topbar */}
<header className="flex h-14 items-center gap-3 border-b border-border/60 px-4">
<p className="text-sm font-medium">Overview</p>
<div className="ml-auto flex items-center gap-2">
<div className="hidden h-8 items-center gap-2 rounded-lg border border-input px-2.5 text-sm text-muted-foreground sm:flex">
<Search className="size-3.5" />
Search
<kbd className="rounded-sm border border-border/60 bg-muted px-1.5 font-mono text-[10px]">
⌘K
</kbd>
</div>
<button
type="button"
aria-label="Notifications"
className="flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
>
<Bell className="size-4" />
</button>
<span className="flex size-8 items-center justify-center rounded-full bg-muted font-mono text-xs font-semibold text-muted-foreground">
NB
</span>
</div>
</header>
{/* Content */}
<div className="grid gap-4 p-4 sm:p-6">
<div className="grid gap-4 sm:grid-cols-3">
{[
{ label: "Deployments today", value: "128" },
{ label: "Error rate", value: "0.02%" },
{ label: "p95 build time", value: "48s" },
].map((stat) => (
<div
key={stat.label}
className="rounded-xl border border-border/60 bg-card p-4"
>
<p className="text-xs text-muted-foreground">{stat.label}</p>
<p className="mt-1.5 text-2xl font-semibold tracking-tight tabular-nums">
{stat.value}
</p>
</div>
))}
</div>
<div className="overflow-hidden rounded-xl border border-border/60">
<div className="border-b border-border/60 bg-card px-4 py-3 text-sm font-medium">
Recent deployments
</div>
{deploys.map((deploy) => (
<div
key={deploy.project}
className="flex items-center justify-between border-b border-border/60 px-4 py-3 last:border-b-0"
>
<div className="flex items-center gap-3">
<span
className={cn(
"size-2 rounded-full",
deploy.status === "Ready"
? "bg-emerald-500"
: "bg-amber-500 animate-status",
)}
/>
<span className="font-mono text-sm">{deploy.project}</span>
<span className="rounded-md bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
{deploy.env}
</span>
</div>
<span className="font-mono text-xs text-muted-foreground">
{deploy.time}
</span>
</div>
))}
</div>
</div>
</div>
</section>
);
}






























