Back to templates components
Analytics Dashboard
A full application dashboard example built with Tailwind CSS, combining a sidebar, topbar, stat cards, revenue and order charts, and a data table into a single page.
0/1 Dark Mode (Request)Updated: N/ANo commit information available.
<input type="checkbox" id="sidebar-toggle" class="peer hidden" />
<label
for="sidebar-toggle"
aria-hidden="true"
class="fixed inset-0 z-30 hidden bg-gray-900/50 peer-checked:block lg:hidden"
></label>
<div
class="fixed inset-y-0 start-0 z-40 flex w-64 -translate-x-full flex-col justify-between overflow-y-auto border-e border-gray-200 bg-white transition-transform duration-300 peer-checked:translate-x-0 lg:static lg:translate-x-0 lg:shrink-0"
>
<div class="p-4">
<span
class="grid h-12 w-32 place-content-center rounded-lg bg-gray-100 text-sm text-gray-600"
>
Logo
</span>
<nav aria-label="Dashboard" class="mt-4">
<ul class="space-y-1">
<li>
<a
href="#"
class="block rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-900"
>
Overview
</a>
</li>
<li>
<a
href="#"
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900"
>
Customers
</a>
</li>
<li>
<a
href="#"
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900"
>
Orders
</a>
</li>
<li>
<a
href="#"
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900"
>
Billing
</a>
</li>
<li>
<a
href="#"
class="block rounded-lg px-4 py-2 text-sm font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900"
>
Settings
</a>
</li>
</ul>
</nav>
</div>
<div class="sticky inset-x-0 bottom-0 border-t border-gray-200">
<a
href="#"
class="flex items-center gap-2 bg-white p-4 hover:bg-gray-50 hover:transition-colors"
>
<img
alt=""
src="https://images.unsplash.com/photo-1600486913747-55e5470d6f40?auto=format&fit=crop&q=80&w=1160"
class="size-10 rounded-full object-cover"
/>
<p class="text-xs text-gray-900">
<strong class="block font-medium">Priya Natarajan</strong>
<span>priya@orbitly.com</span>
</p>
</a>
</div>
</div>
<div class="flex flex-1 flex-col overflow-y-auto">
<header class="flex items-center justify-between border-b border-gray-200 bg-white px-6 py-4">
<div class="flex items-center gap-4">
<label
for="sidebar-toggle"
class="cursor-pointer rounded-md p-2 text-gray-600 transition-colors hover:bg-gray-100 lg:hidden"
>
<span class="sr-only">Toggle menu</span>
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
class="size-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</label>
<h1 class="text-lg font-semibold text-gray-900">Overview</h1>
</div>
<a
href="#"
class="rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-gray-800"
>
New report
</a>
</header>
<main class="flex-1 space-y-6 p-6">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
<article class="flex flex-col gap-4 rounded-lg border border-gray-200 bg-white p-6">
<div class="inline-flex gap-2 self-end rounded-sm bg-green-100 p-1 text-green-600">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
class="size-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"
/>
</svg>
<span class="sr-only">Increase: </span>
<span class="text-xs font-medium">12.4%</span>
</div>
<div>
<strong class="block text-sm font-medium text-gray-600">Monthly revenue</strong>
<p>
<span class="text-2xl font-medium text-gray-900">$48,204</span>
<span class="text-xs text-gray-600">from $42,910</span>
</p>
</div>
<div class="h-10">
<canvas
id="revenue-trend-sparkline"
role="img"
aria-label="Sparkline showing monthly revenue trending upward over the last six months"
></canvas>
</div>
</article>
<article class="flex flex-col gap-4 rounded-lg border border-gray-200 bg-white p-6">
<div class="inline-flex gap-2 self-end rounded-sm bg-green-100 p-1 text-green-600">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
class="size-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"
/>
</svg>
<span class="sr-only">Increase: </span>
<span class="text-xs font-medium">4.1%</span>
</div>
<div>
<strong class="block text-sm font-medium text-gray-600">Active customers</strong>
<p>
<span class="text-2xl font-medium text-gray-900">2,318</span>
<span class="text-xs text-gray-600">from 2,227</span>
</p>
</div>
</article>
<article class="flex flex-col gap-4 rounded-lg border border-gray-200 bg-white p-6">
<div class="inline-flex gap-2 self-end rounded-sm bg-red-100 p-1 text-red-600">
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
class="size-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 17h8m0 0V9m0 8l-8-8-4 4-6-6"
/>
</svg>
<span class="sr-only">Decrease: </span>
<span class="text-xs font-medium">2.6%</span>
</div>
<div>
<strong class="block text-sm font-medium text-gray-600">Churn rate</strong>
<p>
<span class="text-2xl font-medium text-gray-900">1.8%</span>
<span class="text-xs text-gray-600">from 2.1%</span>
</p>
</div>
</article>
</div>
<div class="grid grid-cols-1 gap-4 lg:grid-cols-3">
<div class="rounded-lg border border-gray-200 bg-white p-6 lg:col-span-2">
<div class="flex items-center justify-between">
<h2 class="text-sm font-medium text-gray-900">Revenue trend</h2>
<div class="inline-flex rounded-md border border-gray-200 p-0.5 text-xs font-medium">
<button
type="button"
data-revenue-range="6m"
aria-pressed="true"
class="rounded-sm bg-gray-100 px-2 py-1 text-gray-900"
>
6M
</button>
<button
type="button"
data-revenue-range="12m"
aria-pressed="false"
class="rounded-sm px-2 py-1 text-gray-600"
>
12M
</button>
</div>
</div>
<div class="mt-4 h-64">
<canvas
id="revenue-trend-line-chart"
role="img"
aria-label="Line chart showing monthly revenue rising from $28,000 in January to $48,000 in June"
></canvas>
</div>
</div>
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-sm font-medium text-gray-900">Orders by status</h2>
<div class="mt-4 h-64">
<canvas
id="order-status-donut-chart"
role="img"
aria-label="Donut chart showing 68% of orders paid, 22% pending, and 10% refunded"
></canvas>
</div>
</div>
</div>
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-sm font-medium text-gray-900">Recent orders</h2>
<div class="mt-4 overflow-x-auto">
<table class="min-w-full divide-y-2 divide-gray-200">
<thead class="ltr:text-left rtl:text-right">
<tr class="*:font-medium *:text-gray-900">
<th class="px-3 py-2 whitespace-nowrap">Customer</th>
<th class="px-3 py-2 whitespace-nowrap">Order</th>
<th class="px-3 py-2 whitespace-nowrap">Status</th>
<th class="px-3 py-2 whitespace-nowrap">Amount</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr class="*:text-gray-900 *:first:font-medium">
<td class="px-3 py-2 whitespace-nowrap">Nandor the Relentless</td>
<td class="px-3 py-2 whitespace-nowrap">#3921</td>
<td class="px-3 py-2 whitespace-nowrap">
<span class="rounded-full bg-green-100 px-2.5 py-0.5 text-xs text-green-700">
Paid
</span>
</td>
<td class="px-3 py-2 whitespace-nowrap">$412.00</td>
</tr>
<tr class="*:text-gray-900 *:first:font-medium">
<td class="px-3 py-2 whitespace-nowrap">Laszlo Cravensworth</td>
<td class="px-3 py-2 whitespace-nowrap">#3920</td>
<td class="px-3 py-2 whitespace-nowrap">
<span class="rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs text-yellow-700">
Pending
</span>
</td>
<td class="px-3 py-2 whitespace-nowrap">$128.50</td>
</tr>
<tr class="*:text-gray-900 *:first:font-medium">
<td class="px-3 py-2 whitespace-nowrap">Nadja</td>
<td class="px-3 py-2 whitespace-nowrap">#3919</td>
<td class="px-3 py-2 whitespace-nowrap">
<span class="rounded-full bg-green-100 px-2.5 py-0.5 text-xs text-green-700">
Paid
</span>
</td>
<td class="px-3 py-2 whitespace-nowrap">$894.20</td>
</tr>
<tr class="*:text-gray-900 *:first:font-medium">
<td class="px-3 py-2 whitespace-nowrap">Guillermo de la Cruz</td>
<td class="px-3 py-2 whitespace-nowrap">#3918</td>
<td class="px-3 py-2 whitespace-nowrap">
<span class="rounded-full bg-red-100 px-2.5 py-0.5 text-xs text-red-700">
Refunded
</span>
</td>
<td class="px-3 py-2 whitespace-nowrap">$56.00</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
const revenueTrendSparklineCanvas = document.getElementById('revenue-trend-sparkline')
const revenueTrendLineChartCanvas = document.getElementById('revenue-trend-line-chart')
const orderStatusDonutChartCanvas = document.getElementById('order-status-donut-chart')
const revenueRangeButtons = document.querySelectorAll('[data-revenue-range]')
const revenueRangesByPeriod = {
'6m': {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
values: [28000, 34000, 31000, 39000, 42000, 48000],
},
'12m': {
labels: ['Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
values: [
19000, 21500, 20000, 23500, 25000, 27000, 28000, 34000, 31000, 39000, 42000, 48000,
],
},
}
new Chart(revenueTrendSparklineCanvas, {
type: 'line',
data: {
labels: revenueRangesByPeriod['6m'].labels,
datasets: [
{
data: revenueRangesByPeriod['6m'].values,
borderColor: '#10b981',
borderWidth: 2,
pointRadius: 0,
tension: 0.35,
fill: false,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: { enabled: false },
},
scales: {
x: { display: false },
y: { display: false },
},
},
})
const revenueTrendChartContext = revenueTrendLineChartCanvas.getContext('2d')
const revenueTrendFillGradient = revenueTrendChartContext.createLinearGradient(0, 0, 0, 256)
revenueTrendFillGradient.addColorStop(0, 'rgba(79, 70, 229, 0.25)')
revenueTrendFillGradient.addColorStop(1, 'rgba(79, 70, 229, 0)')
const revenueTrendLineChart = new Chart(revenueTrendLineChartCanvas, {
type: 'line',
data: {
labels: revenueRangesByPeriod['6m'].labels,
datasets: [
{
label: 'Revenue',
data: revenueRangesByPeriod['6m'].values,
borderColor: '#4f46e5',
backgroundColor: revenueTrendFillGradient,
borderWidth: 2,
pointRadius: 0,
pointHoverRadius: 5,
pointHoverBackgroundColor: '#4f46e5',
pointHoverBorderColor: '#ffffff',
pointHoverBorderWidth: 2,
tension: 0.35,
fill: true,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (tooltipItem) => `$${tooltipItem.formattedValue}`,
},
},
},
scales: {
x: {
grid: { display: false },
ticks: { color: '#4b5563' },
},
y: {
beginAtZero: true,
grid: { color: '#e5e7eb' },
ticks: {
color: '#4b5563',
callback: (tickValue) => `$${Number(tickValue) / 1000}k`,
},
},
},
},
})
revenueRangeButtons.forEach((revenueRangeButton) => {
revenueRangeButton.addEventListener('click', () => {
const selectedRange = revenueRangeButton.dataset.revenueRange
revenueRangeButtons.forEach((otherRangeButton) => {
const isSelectedButton = otherRangeButton === revenueRangeButton
otherRangeButton.setAttribute('aria-pressed', String(isSelectedButton))
otherRangeButton.classList.toggle('bg-gray-100', isSelectedButton)
otherRangeButton.classList.toggle('text-gray-900', isSelectedButton)
otherRangeButton.classList.toggle('text-gray-600', !isSelectedButton)
})
revenueTrendLineChart.data.labels = revenueRangesByPeriod[selectedRange].labels
revenueTrendLineChart.data.datasets[0].data = revenueRangesByPeriod[selectedRange].values
revenueTrendLineChart.update()
})
})
new Chart(orderStatusDonutChartCanvas, {
type: 'doughnut',
data: {
labels: ['Paid', 'Pending', 'Refunded'],
datasets: [
{
data: [68, 22, 10],
backgroundColor: ['#10b981', '#f59e0b', '#f43f5e'],
hoverBackgroundColor: ['#059669', '#d97706', '#e11d48'],
borderColor: '#ffffff',
borderWidth: 2,
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '70%',
plugins: {
legend: {
position: 'bottom',
labels: { color: '#4b5563' },
},
tooltip: {
callbacks: {
label: (tooltipItem) => `${tooltipItem.label}: ${tooltipItem.formattedValue}%`,
},
},
},
},
})
</script>Plugins: chart.js
Components used
- Sidebar navigation: Logo, links with accordion menu and profile details
- Stat cards: Title, value, from value and themed growth stat
- Revenue trend chart: Line chart with filled area and range toggle
- Orders by status chart: Donut chart with legend
- Revenue sparkline: Sparkline for stat cards
- Orders table: Base