Section

Dashboard Overview — Vercel

Refined dark monochrome analytics dashboard overview with KPI stat cards and trend deltas, a pure-SVG area + line chart, a recent-activity feed, and a wired 7d/30d/90d range selector that swaps hardcoded datasets live. Hairline borders, generous spacing, and a single teal accent.

  • Section
  • Tailwind
  • HTML
  • MIT

Preview

Live section

Interactive preview
Open preview
9:41 100%
devsnips.dev/library/tailwind/sections/app-ui/dashboard-overview/vercel/
fluid · no fixed width 100%
Dependencies: Tailwind CSS (CDN) · Google Fonts: Geist, Geist Mono Responsive · Keyboard-ready

Install

Add to your project

terminal
npx devsnips add Tailwind/Sections/App-UI/dashboard-overview/vercel
registry path: Tailwind/Sections/App-UI/dashboard-overview/vercel

Source

Implementation

code.html
<!--
Snippet Name: Dashboard Overview — Vercel
Description: Refined dark monochrome analytics dashboard with KPI stat cards, a pure-SVG area+line chart, an activity feed, and a wired 7d/30d/90d range selector that swaps hardcoded datasets. Hairline borders, a single teal accent.
Author: DevSnips Contributors
Usage Example: Drop into a dark product shell as an analytics overview. The range selector updates KPI values, deltas, and the chart in preview.html.
-->
<div class="relative w-full" data-dash="vc">

  <!-- Panel -->
  <div class="overflow-hidden rounded-[14px] border border-white/10 bg-[#0a0a0a] shadow-[0_0_0_1px_rgba(255,255,255,0.02),0_20px_60px_-20px_rgba(0,0,0,0.9)]">
    <!-- top radial glow -->
    <div class="pointer-events-none absolute inset-x-0 top-0 -z-0 h-40 [background:radial-gradient(60%_100%_at_50%_0%,rgba(80,227,194,0.10),transparent_70%)]" aria-hidden="true"></div>

    <!-- Header / toolbar -->
    <div class="relative flex flex-col gap-4 border-b border-white/[0.07] px-5 py-4 sm:flex-row sm:items-center sm:justify-between sm:px-6">
      <div class="flex items-center gap-3">
        <div class="flex h-9 w-9 items-center justify-center rounded-lg border border-white/10 bg-white text-black">
          <svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M3 17l5-6 4 4 4-6 5 5" /></svg>
        </div>
        <div class="leading-tight">
          <p class="font-g text-[15px] font-semibold text-white">Overview</p>
          <p class="vc-mono mt-1 text-[11px] text-white/40">
            <span class="vc-dot"></span>live · updated 2m ago
          </p>
        </div>
      </div>

      <div role="group" aria-label="Time range" class="flex w-fit items-center rounded-lg border border-white/10 bg-white/[0.03] p-0.5">
        <button type="button" data-range="7" class="vc-range rounded-md px-3 py-1.5 font-mono text-[11px] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">7d</button>
        <button type="button" data-range="30" class="vc-range rounded-md px-3 py-1.5 font-mono text-[11px] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">30d</button>
        <button type="button" data-range="90" class="vc-range rounded-md px-3 py-1.5 font-mono text-[11px] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">90d</button>
      </div>
    </div>

    <!-- KPI cards -->
    <div class="grid grid-cols-1 gap-px border-b border-white/[0.07] bg-white/[0.04] sm:grid-cols-2 lg:grid-cols-4">
      <div class="bg-[#0a0a0a] p-5" data-kpi="revenue">
        <div class="flex items-center justify-between">
          <p class="vc-mono text-[11px] uppercase tracking-wider text-white/40">Revenue</p>
          <svg class="h-4 w-4 text-white/30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 1v23M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" /></svg>
        </div>
        <p class="mt-3 font-g text-2xl font-semibold text-white" data-kpi-value>$48,210</p>
        <p class="vc-mono mt-1.5 flex items-center gap-1 text-[11px]" data-kpi-delta>
          <span class="text-[#50e3c2]">▲ +12.4%</span><span class="text-white/35">vs prev</span>
        </p>
      </div>
      <div class="bg-[#0a0a0a] p-5" data-kpi="users">
        <div class="flex items-center justify-between">
          <p class="vc-mono text-[11px] uppercase tracking-wider text-white/40">Active Users</p>
          <svg class="h-4 w-4 text-white/30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" /></svg>
        </div>
        <p class="mt-3 font-g text-2xl font-semibold text-white" data-kpi-value>18,402</p>
        <p class="vc-mono mt-1.5 flex items-center gap-1 text-[11px]" data-kpi-delta>
          <span class="text-[#50e3c2]">▲ +8.1%</span><span class="text-white/35">vs prev</span>
        </p>
      </div>
      <div class="bg-[#0a0a0a] p-5" data-kpi="mrr">
        <div class="flex items-center justify-between">
          <p class="vc-mono text-[11px] uppercase tracking-wider text-white/40">MRR</p>
          <svg class="h-4 w-4 text-white/30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 3v18h18M7 14l3-3 3 3 5-6" /></svg>
        </div>
        <p class="mt-3 font-g text-2xl font-semibold text-white" data-kpi-value>$12,640</p>
        <p class="vc-mono mt-1.5 flex items-center gap-1 text-[11px]" data-kpi-delta>
          <span class="text-[#50e3c2]">▲ +5.7%</span><span class="text-white/35">vs prev</span>
        </p>
      </div>
      <div class="bg-[#0a0a0a] p-5" data-kpi="churn">
        <div class="flex items-center justify-between">
          <p class="vc-mono text-[11px] uppercase tracking-wider text-white/40">Churn</p>
          <svg class="h-4 w-4 text-white/30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 12a9 9 0 1 1-3-6.7L21 8" /></svg>
        </div>
        <p class="mt-3 font-g text-2xl font-semibold text-white" data-kpi-value>2.1%</p>
        <p class="vc-mono mt-1.5 flex items-center gap-1 text-[11px]" data-kpi-delta>
          <span class="text-[#50e3c2]">▼ -0.3pp</span><span class="text-white/35">good</span>
        </p>
      </div>
    </div>

    <!-- Chart + activity -->
    <div class="grid grid-cols-1 lg:grid-cols-3">
      <!-- Chart -->
      <div class="border-b border-white/[0.07] p-5 sm:p-6 lg:col-span-2 lg:border-b-0 lg:border-r lg:border-white/[0.07]">
        <div class="mb-5 flex flex-wrap items-end justify-between gap-3">
          <div>
            <p class="font-g text-[14px] font-medium text-white">Revenue Trend</p>
            <p class="vc-mono mt-1 text-[11px] text-white/40">last <span data-range-label>30 days</span></p>
          </div>
          <div class="flex items-center gap-4">
            <span class="flex items-center gap-1.5 vc-mono text-[11px] text-white/55">
              <span class="inline-block h-2 w-2 rounded-full bg-[#50e3c2]"></span>Revenue
            </span>
            <span class="flex items-center gap-1.5 vc-mono text-[11px] text-white/55">
              <span class="inline-block h-2 w-2 rounded-full bg-white/30"></span>Prev period
            </span>
          </div>
        </div>
        <div class="relative">
          <svg data-chart viewBox="0 0 640 240" preserveAspectRatio="none" class="h-56 w-full sm:h-64" role="img" aria-label="Revenue trend chart"></svg>
          <div class="mt-2 flex items-center justify-between vc-mono text-[10px] text-white/35" data-chart-axis></div>
        </div>
      </div>

      <!-- Activity feed -->
      <div class="p-5 sm:p-6">
        <div class="mb-4 flex items-center justify-between">
          <p class="font-g text-[14px] font-medium text-white">Recent Activity</p>
          <button type="button" class="vc-mono text-[11px] text-white/40 transition-colors hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">All</button>
        </div>
        <ul class="space-y-3" data-activity>
          <li class="flex gap-3 rounded-lg border border-white/[0.07] bg-white/[0.02] p-3 transition-colors hover:bg-white/[0.05]">
            <span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-white/10 bg-[#50e3c2]/10 text-[#50e3c2]">
              <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14" /></svg>
            </span>
            <div class="min-w-0 flex-1">
              <p class="font-g text-[13px] text-white/90">New customer upgrade</p>
              <p class="vc-mono mt-0.5 text-[11px] text-white/35">acme-co · pro · 2m</p>
            </div>
          </li>
          <li class="flex gap-3 rounded-lg border border-white/[0.07] bg-white/[0.02] p-3 transition-colors hover:bg-white/[0.05]">
            <span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white/5 text-white/70">
              <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
            </span>
            <div class="min-w-0 flex-1">
              <p class="font-g text-[13px] text-white/90">Payout processed</p>
              <p class="vc-mono mt-0.5 text-[11px] text-white/35">stripe · $4,820 · 38m</p>
            </div>
          </li>
          <li class="flex gap-3 rounded-lg border border-white/[0.07] bg-white/[0.02] p-3 transition-colors hover:bg-white/[0.05]">
            <span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white/5 text-white/70">
              <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M6 9l6 6 6-6" /></svg>
            </span>
            <div class="min-w-0 flex-1">
              <p class="font-g text-[13px] text-white/90">Churn alert resolved</p>
              <p class="vc-mono mt-0.5 text-[11px] text-white/35">quark.io · 1h</p>
            </div>
          </li>
          <li class="flex gap-3 rounded-lg border border-white/[0.07] bg-white/[0.02] p-3 transition-colors hover:bg-white/[0.05]">
            <span class="flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white/5 text-white/70">
              <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><circle cx="12" cy="12" r="3" /><path d="M12 2v3M12 19v3M2 12h3M19 12h3" /></svg>
            </span>
            <div class="min-w-0 flex-1">
              <p class="font-g text-[13px] text-white/90">New trial signup</p>
              <p class="vc-mono mt-0.5 text-[11px] text-white/35">loop-labs · 3h</p>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>

  <script>
    (function () {
      var root = document.currentScript.closest('[data-dash]');
      if (!root) return;

      var datasets = {
        7: {
          labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
          current: [42, 55, 48, 71, 66, 80, 95],
          previous: [38, 47, 52, 60, 58, 70, 82],
          kpis: {
            revenue: { value: '$11,420', delta: '▲ +9.2%', color: '#50e3c2' },
            users: { value: '4,820', delta: '▲ +6.4%', color: '#50e3c2' },
            mrr: { value: '$12,640', delta: '▲ +5.7%', color: '#50e3c2' },
            churn: { value: '2.1%', delta: '▼ -0.3pp', color: '#50e3c2', note: 'good' }
          }
        },
        30: {
          labels: ['W1', 'W2', 'W3', 'W4'],
          current: [320, 410, 380, 510],
          previous: [280, 360, 340, 460],
          kpis: {
            revenue: { value: '$48,210', delta: '▲ +12.4%', color: '#50e3c2' },
            users: { value: '18,402', delta: '▲ +8.1%', color: '#50e3c2' },
            mrr: { value: '$12,640', delta: '▲ +5.7%', color: '#50e3c2' },
            churn: { value: '2.1%', delta: '▼ -0.3pp', color: '#50e3c2', note: 'good' }
          }
        },
        90: {
          labels: ['M1', 'M2', 'M3'],
          current: [1480, 1720, 1610],
          previous: [1260, 1520, 1450],
          kpis: {
            revenue: { value: '$142,080', delta: '▲ +18.6%', color: '#50e3c2' },
            users: { value: '52,140', delta: '▲ +14.2%', color: '#50e3c2' },
            mrr: { value: '$13,920', delta: '▲ +9.3%', color: '#50e3c2' },
            churn: { value: '1.9%', delta: '▼ -0.4pp', color: '#50e3c2', note: 'good' }
          }
        }
      };

      var chart = root.querySelector('[data-chart]');
      var axis = root.querySelector('[data-chart-axis]');
      var rangeLabel = root.querySelector('[data-range-label]');
      var buttons = root.querySelectorAll('.vc-range');

      function smoothPath(pts) {
        if (pts.length < 2) return '';
        var d = 'M ' + pts[0].x.toFixed(1) + ' ' + pts[0].y.toFixed(1);
        for (var i = 1; i < pts.length; i++) {
          var p0 = pts[i - 1], p1 = pts[i];
          var cx = (p0.x + p1.x) / 2;
          d += ' C ' + cx.toFixed(1) + ' ' + p0.y.toFixed(1) + ' ' + cx.toFixed(1) + ' ' + p1.y.toFixed(1) + ' ' + p1.x.toFixed(1) + ' ' + p1.y.toFixed(1);
        }
        return d;
      }

      function render(range) {
        var d = datasets[range];
        if (!d) return;

        ['revenue', 'users', 'mrr', 'churn'].forEach(function (key) {
          var card = root.querySelector('[data-kpi="' + key + '"]');
          if (!card) return;
          var k = d.kpis[key];
          var valEl = card.querySelector('[data-kpi-value]');
          var dEl = card.querySelector('[data-kpi-delta]');
          if (valEl) valEl.textContent = k.value;
          if (dEl) {
            var note = k.note === 'good' ? 'good' : 'vs prev';
            dEl.innerHTML = '<span style="color:' + k.color + '">' + k.delta + '</span><span class="text-white/35">' + note + '</span>';
          }
        });

        if (rangeLabel) rangeLabel.textContent = range + ' days';

        var W = 640, H = 240, padB = 22, padT = 14, padX = 18;
        var n = d.current.length;
        var max = Math.max.apply(null, d.current.concat(d.previous)) * 1.15;
        var innerW = W - padX * 2;
        var innerH = H - padT - padB;
        var xAt = function (i) { return padX + (n === 1 ? innerW / 2 : (innerW * i) / (n - 1)); };
        var yAt = function (v) { return padT + innerH - (v / max) * innerH; };

        var curPts = d.current.map(function (v, i) { return { x: xAt(i), y: yAt(v) }; });
        var prevPts = d.previous.map(function (v, i) { return { x: xAt(i), y: yAt(v) }; });
        var curPath = smoothPath(curPts);
        var prevPath = smoothPath(prevPts);
        var areaPath = curPath + ' L ' + xAt(n - 1).toFixed(1) + ' ' + (H - padB) + ' L ' + xAt(0).toFixed(1) + ' ' + (H - padB) + ' Z';

        var svg = '';
        // gridlines
        for (var g = 0; g <= 4; g++) {
          var gy = padT + innerH * (g / 4);
          svg += '<line x1="' + padX + '" y1="' + gy.toFixed(1) + '" x2="' + (W - padX) + '" y2="' + gy.toFixed(1) + '" stroke="rgba(255,255,255,0.06)" stroke-width="1"/>';
        }
        // defs gradient
        svg += '<defs><linearGradient id="vcArea" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#50e3c2" stop-opacity="0.35"/><stop offset="100%" stop-color="#50e3c2" stop-opacity="0"/></linearGradient></defs>';
        // previous line
        svg += '<path d="' + prevPath + '" fill="none" stroke="rgba(255,255,255,0.25)" stroke-width="1.5" stroke-dasharray="3 3"/>';
        // current area
        svg += '<path d="' + areaPath + '" fill="url(#vcArea)"/>';
        // current line
        svg += '<path d="' + curPath + '" fill="none" stroke="#50e3c2" stroke-width="2" stroke-linecap="round"/>';
        // points
        curPts.forEach(function (p) {
          svg += '<circle cx="' + p.x.toFixed(1) + '" cy="' + p.y.toFixed(1) + '" r="3" fill="#0a0a0a" stroke="#50e3c2" stroke-width="2"/>';
        });
        // baseline
        svg += '<line x1="' + padX + '" y1="' + (H - padB) + '" x2="' + (W - padX) + '" y2="' + (H - padB) + '" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>';
        chart.innerHTML = svg;

        if (axis) axis.innerHTML = d.labels.map(function (l) { return '<span>' + l + '</span>'; }).join('');

        buttons.forEach(function (b) {
          var active = b.dataset.range === String(range);
          b.classList.toggle('bg-white', active);
          b.classList.toggle('text-black', active);
          b.classList.toggle('text-white/55', !active);
          if (active) b.setAttribute('aria-pressed', 'true'); else b.removeAttribute('aria-pressed');
        });
      }

      buttons.forEach(function (b) {
        b.addEventListener('click', function () { render(parseInt(b.dataset.range, 10)); });
      });

      render(30);
    })();
  </script>
</div>
281 lines UTF-8 · LF · Spaces: 2

AI-ready

Available to your agent.

This section is reachable through the DevSnips CLI, MCP server and Skills integrations — one registry, one resource path.

Resource path

devsnips://sections/app-ui/dashboard-overview/vercel

Continue browsing

View all