Dashboard
The dashboard pattern is used for overview pages that aggregate data into summaries, charts, and quick actions. Examples include the weather dashboard, news overview, and event analytics.
Anatomy
A dashboard page consists of:
- Header — page title, date range picker, and global actions
- Stats row — key metrics displayed as stat cards
- Primary chart — the main data visualization
- Secondary panels — supporting charts, tables, or activity feeds
- Quick actions — shortcuts to common tasks
Layout
Use the DashboardLayout component for the sidebar + content structure:
<DashboardLayout>
<MukokoSidebar />
<main className="flex-1 p-4 sm:p-6">
{/* Header */}
<div className="flex items-center justify-between">
<h1 className="font-serif text-2xl font-bold">Dashboard</h1>
<DatePicker />
</div>
{/* Stats */}
<div className="mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
<StatsCard title="Total views" value="12,345" change="+12%" />
<StatsCard title="Active users" value="1,234" change="+5%" />
<StatsCard title="Revenue" value="$8,901" change="+8%" />
<StatsCard title="Events" value="42" change="+3%" />
</div>
{/* Charts */}
<div className="mt-6 grid gap-4 lg:grid-cols-[2fr_1fr]">
<Card>{/* Primary chart */}</Card>
<Card>{/* Secondary panel */}</Card>
</div>
</main>
</DashboardLayout>Stats cards
Use the StatsCard component for key metrics:
<StatsCard
title="Total events"
value="1,247"
change="+12%"
description="Compared to last month"
/>Arrange stats in a responsive grid that collapses on mobile:
<div className="grid gap-4 grid-cols-2 lg:grid-cols-4">
<StatsCard title="Views" value="12.3K" />
<StatsCard title="Users" value="1.2K" />
<StatsCard title="Revenue" value="$8.9K" />
<StatsCard title="Growth" value="+12%" />
</div>Chart integration
Use the chart component with Recharts for data visualization. Charts automatically use the Five African Minerals chart tokens:
const chartConfig = {
views: { label: "Views", color: "var(--chart-1)" },
users: { label: "Users", color: "var(--chart-2)" },
}
<ChartContainer config={chartConfig} className="h-[300px]">
<AreaChart data={data}>
<Area dataKey="views" fill="var(--chart-1)" stroke="var(--chart-1)" />
<Area dataKey="users" fill="var(--chart-2)" stroke="var(--chart-2)" />
<ChartTooltip content={<ChartTooltipContent />} />
</AreaChart>
</ChartContainer>Grid patterns
Two-column with emphasis
Large chart on the left, narrow panel on the right:
<div className="grid gap-4 lg:grid-cols-[2fr_1fr]">
<Card className="p-6">{/* Primary chart */}</Card>
<Card className="p-6">{/* Activity feed or secondary chart */}</Card>
</div>Three-column equal
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<Card className="p-6">{/* Chart 1 */}</Card>
<Card className="p-6">{/* Chart 2 */}</Card>
<Card className="p-6">{/* Chart 3 */}</Card>
</div>Mobile dashboards
On mobile, dashboards stack vertically. Prioritize information:
- Stats cards — always visible (2-column grid on mobile)
- Primary chart — full width
- Secondary panels — below, in order of importance
- Data tables — use horizontal scroll or switch to card view
{/* Responsive table/card switch */}
<div className="hidden sm:block">
<DataTable columns={columns} data={data} />
</div>
<div className="sm:hidden space-y-3">
{data.map((item) => (
<Card key={item.id} className="p-4">
<p className="font-medium">{item.name}</p>
<p className="text-sm text-muted-foreground">{item.value}</p>
</Card>
))}
</div>Refresh and real-time
For dashboards that update periodically:
- Show the last refresh time in the header
- Use skeleton loading for sections that are refreshing
- Avoid full-page loading states — update individual sections independently
Last updated on