Recipes · Layout

Dashboard

A three-region app shell with a sidebar, a stat header, and a data table. Every element is a Nova primitive — no custom CSS beyond the utility layer.

Preview

The layout below is the actual composition. Resize the preview to see how it stacks.

Nova Console

Active users

12,481

+8.2%

MRR

$42,908

+3.1%

Latency p95

184ms

-12ms

Recent customers

NamePlanStatus
Ada LovelaceTeamActive
Grace HopperProTrialing
Radia PerlmanTeamActive
+1
4 admins online
Updated 2s ago

Full source

tsx
import { Avatar, AvatarGroup, Badge, Button, Card, IconButton, Input, Separator } from "@novix-ui/react";
import { ArrowUpRight, Bell, ChevronRight, Search } from "lucide-react";
 
const KPIS = [
{ label: "Active users", value: "12,481", delta: "+8.2%" },
{ label: "MRR", value: "$42,908", delta: "+3.1%" },
{ label: "Latency p95", value: "184ms", delta: "-12ms" },
];
 
const ROWS = [
{ name: "Ada Lovelace", plan: "Team", status: "Active" },
{ name: "Grace Hopper", plan: "Pro", status: "Trialing" },
{ name: "Radia Perlman", plan: "Team", status: "Active" },
];
 
export function Dashboard() {
return (
<div className="rounded-xl border bg-background">
<header className="flex items-center justify-between border-b px-4 py-3">
<div className="flex items-center gap-3">
<div className="size-6 rounded-md bg-accent" />
<p className="font-semibold">Nova Console</p>
</div>
<div className="flex items-center gap-2">
<Input leadingIcon={<Search className="size-4" />} placeholder="Search…" className="h-8" />
<IconButton aria-label="Notifications"><Bell /></IconButton>
<Avatar name="Ada Lovelace" size="sm" />
</div>
</header>
 
<div className="grid gap-3 p-4 sm:grid-cols-3">
{KPIS.map((k) => (
<Card key={k.label} className="p-4">
<p className="text-xs text-muted-foreground">{k.label}</p>
<p className="mt-1 text-xl font-semibold">{k.value}</p>
<Badge variant="outline" size="sm" className="mt-2">{k.delta}</Badge>
</Card>
))}
</div>
 
<Separator />
 
<section className="p-4">
<div className="mb-3 flex items-center justify-between">
<p className="font-semibold">Recent customers</p>
<Button variant="ghost" size="sm" trailingIcon={<ArrowUpRight className="size-4" />}>
View all
</Button>
</div>
{/* table */}
</section>
</div>
);
}

Anatomy

  • Top bar — brand, global Search input, notifications IconButton, user Avatar.
  • KPI row — three Cards side-by-side. Use grid-cols-3 on lg, stack on mobile.
  • Table — semantic HTML with subtle striping. Wrap rows in Link when navigable.
  • Footer strip — AvatarGroup for presence, timestamp on the right.

Swap in your data

Replace the local KPIS and ROWS arrays with your loader data. Add Skeleton placeholders while data is in flight.