Skip to content
HyperUI

No results found.

Back to application components

Charts

Chart components for visualizing trends, comparisons, and breakdowns in dashboards and analytics pages, built with Chart.js.

11/11 Dark Mode Updated: N/ANo commit information available.
<div class="rounded-lg border border-gray-200 bg-white p-6">
  <div class="flex items-center justify-between">
    <h2 class="text-sm font-medium text-gray-900">Monthly revenue</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-line-chart"
      role="img"
      aria-label="Monthly revenue, line chart"
    ></canvas>
  </div>

  <table id="revenue-line-chart-table" class="sr-only" aria-live="polite">
    <caption>
      Monthly revenue by month
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
      </tr>
    </thead>
    <tbody></tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueLineChartCanvas = document.getElementById('revenue-line-chart')
  const revenueLineChartTableBody = document.querySelector('#revenue-line-chart-table tbody')
  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,
      ],
    },
  }

  const chartCanvasContext = revenueLineChartCanvas.getContext('2d')
  const revenueFillGradient = chartCanvasContext.createLinearGradient(0, 0, 0, 256)

  revenueFillGradient.addColorStop(0, 'rgba(79, 70, 229, 0.25)')
  revenueFillGradient.addColorStop(1, 'rgba(79, 70, 229, 0)')

  const revenueLineChart = new Chart(revenueLineChartCanvas, {
    type: 'line',
    data: {
      labels: revenueRangesByPeriod['6m'].labels,
      datasets: [
        {
          label: 'Revenue',
          data: revenueRangesByPeriod['6m'].values,
          borderColor: '#4f46e5',
          backgroundColor: revenueFillGradient,
          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`,
          },
        },
      },
    },
  })

  function renderRevenueTableRows(selectedRange) {
    const { labels, values } = revenueRangesByPeriod[selectedRange]

    revenueLineChartTableBody.innerHTML = labels
      .map(
        (monthLabel, monthIndex) => `
          <tr>
            <th scope="row">${monthLabel}</th>
            <td>$${values[monthIndex].toLocaleString()}</td>
          </tr>
        `,
      )
      .join('')
  }

  renderRevenueTableRows('6m')

  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)
      })

      revenueLineChart.data.labels = revenueRangesByPeriod[selectedRange].labels
      revenueLineChart.data.datasets[0].data = revenueRangesByPeriod[selectedRange].values
      revenueLineChart.update()

      renderRevenueTableRows(selectedRange)
    })
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <div class="flex items-center justify-between">
    <h2 class="text-sm font-medium text-white">Monthly revenue</h2>

    <div class="inline-flex rounded-md border border-gray-700 p-0.5 text-xs font-medium">
      <button
        type="button"
        data-revenue-range="6m"
        aria-pressed="true"
        class="rounded-sm bg-gray-800 px-2 py-1 text-white"
      >
        6M
      </button>

      <button
        type="button"
        data-revenue-range="12m"
        aria-pressed="false"
        class="rounded-sm px-2 py-1 text-gray-400"
      >
        12M
      </button>
    </div>
  </div>

  <div class="mt-4 h-64">
    <canvas
      id="revenue-line-chart"
      role="img"
      aria-label="Monthly revenue, line chart"
    ></canvas>
  </div>

  <table id="revenue-line-chart-table" class="sr-only" aria-live="polite">
    <caption>
      Monthly revenue by month
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
      </tr>
    </thead>
    <tbody></tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueLineChartCanvas = document.getElementById('revenue-line-chart')
  const revenueLineChartTableBody = document.querySelector('#revenue-line-chart-table tbody')
  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,
      ],
    },
  }

  const chartCanvasContext = revenueLineChartCanvas.getContext('2d')
  const revenueFillGradient = chartCanvasContext.createLinearGradient(0, 0, 0, 256)

  revenueFillGradient.addColorStop(0, 'rgba(129, 140, 248, 0.3)')
  revenueFillGradient.addColorStop(1, 'rgba(129, 140, 248, 0)')

  const revenueLineChart = new Chart(revenueLineChartCanvas, {
    type: 'line',
    data: {
      labels: revenueRangesByPeriod['6m'].labels,
      datasets: [
        {
          label: 'Revenue',
          data: revenueRangesByPeriod['6m'].values,
          borderColor: '#818cf8',
          backgroundColor: revenueFillGradient,
          borderWidth: 2,
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#818cf8',
          pointHoverBorderColor: '#111827',
          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: '#9ca3af' },
        },
        y: {
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: {
            color: '#9ca3af',
            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-800', isSelectedButton)
        otherRangeButton.classList.toggle('text-white', isSelectedButton)
        otherRangeButton.classList.toggle('text-gray-400', !isSelectedButton)
      })

      revenueLineChart.data.labels = revenueRangesByPeriod[selectedRange].labels
      revenueLineChart.data.datasets[0].data = revenueRangesByPeriod[selectedRange].values
      revenueLineChart.update()
    })
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Orders this week</h2>

  <div class="mt-4 h-64">
    <canvas
      id="weekly-orders-bar-chart"
      role="img"
      aria-label="Orders this week, bar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Orders per day this week
    </caption>
    <thead>
      <tr>
        <th scope="col">Day</th>
        <th scope="col">Orders</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Mon</th>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">Tue</th>
        <td>19</td>
      </tr>
      <tr>
        <th scope="row">Wed</th>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">Thu</th>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">Fri</th>
        <td>27</td>
      </tr>
      <tr>
        <th scope="row">Sat</th>
        <td>32</td>
      </tr>
      <tr>
        <th scope="row">Sun</th>
        <td>18</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const weeklyOrdersBarChartCanvas = document.getElementById('weekly-orders-bar-chart')

  new Chart(weeklyOrdersBarChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      datasets: [
        {
          label: 'Orders',
          data: [12, 19, 14, 22, 27, 32, 18],
          backgroundColor: '#6366f1',
          hoverBackgroundColor: '#4338ca',
          borderRadius: 4,
          maxBarThickness: 32,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: { display: false },
        tooltip: {
          callbacks: {
            label: (tooltipItem) => `${tooltipItem.formattedValue} orders`,
          },
        },
      },
      scales: {
        x: {
          grid: { display: false },
          ticks: { color: '#4b5563' },
        },
        y: {
          beginAtZero: true,
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Orders this week</h2>

  <div class="mt-4 h-64">
    <canvas
      id="weekly-orders-bar-chart"
      role="img"
      aria-label="Orders this week, bar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Orders per day this week
    </caption>
    <thead>
      <tr>
        <th scope="col">Day</th>
        <th scope="col">Orders</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Mon</th>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">Tue</th>
        <td>19</td>
      </tr>
      <tr>
        <th scope="row">Wed</th>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">Thu</th>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">Fri</th>
        <td>27</td>
      </tr>
      <tr>
        <th scope="row">Sat</th>
        <td>32</td>
      </tr>
      <tr>
        <th scope="row">Sun</th>
        <td>18</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const weeklyOrdersBarChartCanvas = document.getElementById('weekly-orders-bar-chart')

  new Chart(weeklyOrdersBarChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      datasets: [
        {
          label: 'Orders',
          data: [12, 19, 14, 22, 27, 32, 18],
          backgroundColor: '#818cf8',
          hoverBackgroundColor: '#a5b4fc',
          borderRadius: 4,
          maxBarThickness: 32,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: { display: false },
        tooltip: {
          callbacks: {
            label: (tooltipItem) => `${tooltipItem.formattedValue} orders`,
          },
        },
      },
      scales: {
        x: {
          grid: { display: false },
          ticks: { color: '#9ca3af' },
        },
        y: {
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<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="Orders by status, donut chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Orders by status
    </caption>
    <thead>
      <tr>
        <th scope="col">Status</th>
        <th scope="col">Percentage</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Paid</th>
        <td>68%</td>
      </tr>
      <tr>
        <th scope="row">Pending</th>
        <td>22%</td>
      </tr>
      <tr>
        <th scope="row">Refunded</th>
        <td>10%</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const orderStatusDonutChartCanvas = document.getElementById('order-status-donut-chart')

  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

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Orders by status</h2>

  <div class="mt-4 h-64">
    <canvas
      id="order-status-donut-chart"
      role="img"
      aria-label="Orders by status, donut chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Orders by status
    </caption>
    <thead>
      <tr>
        <th scope="col">Status</th>
        <th scope="col">Percentage</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Paid</th>
        <td>68%</td>
      </tr>
      <tr>
        <th scope="row">Pending</th>
        <td>22%</td>
      </tr>
      <tr>
        <th scope="row">Refunded</th>
        <td>10%</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const orderStatusDonutChartCanvas = document.getElementById('order-status-donut-chart')

  new Chart(orderStatusDonutChartCanvas, {
    type: 'doughnut',
    data: {
      labels: ['Paid', 'Pending', 'Refunded'],
      datasets: [
        {
          data: [68, 22, 10],
          backgroundColor: ['#34d399', '#fbbf24', '#fb7185'],
          hoverBackgroundColor: ['#10b981', '#f59e0b', '#f43f5e'],
          borderColor: '#111827',
          borderWidth: 2,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      cutout: '70%',
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) => `${tooltipItem.label}: ${tooltipItem.formattedValue}%`,
          },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div
  class="flex items-center justify-between gap-4 rounded-lg border border-gray-200 bg-white p-6"
>
  <div>
    <strong class="block text-sm font-medium text-gray-600">Monthly revenue</strong>

    <p class="text-2xl font-medium text-gray-900">$48,204</p>
  </div>

  <div class="h-12 w-24 shrink-0">
    <canvas
      id="revenue-sparkline-chart"
      role="img"
      aria-label="Monthly revenue trend, sparkline chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue by month
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueSparklineChartCanvas = document.getElementById('revenue-sparkline-chart')

  new Chart(revenueSparklineChartCanvas, {
    type: 'line',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          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 },
      },
    },
  })
</script>

Plugins: chart.js

<div
  class="flex items-center justify-between gap-4 rounded-lg border border-gray-800 bg-gray-900 p-6"
>
  <div>
    <strong class="block text-sm font-medium text-gray-400">Monthly revenue</strong>

    <p class="text-2xl font-medium text-white">$48,204</p>
  </div>

  <div class="h-12 w-24 shrink-0">
    <canvas
      id="revenue-sparkline-chart"
      role="img"
      aria-label="Monthly revenue trend, sparkline chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue by month
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueSparklineChartCanvas = document.getElementById('revenue-sparkline-chart')

  new Chart(revenueSparklineChartCanvas, {
    type: 'line',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          borderColor: '#34d399',
          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 },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Traffic by channel</h2>

  <div class="mt-4 h-64">
    <canvas
      id="channel-traffic-stacked-bar-chart"
      role="img"
      aria-label="Traffic by channel, stacked bar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Website traffic by channel, per day
    </caption>
    <thead>
      <tr>
        <th scope="col">Day</th>
        <th scope="col">Organic</th>
        <th scope="col">Paid</th>
        <th scope="col">Referral</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Mon</th>
        <td>120</td>
        <td>80</td>
        <td>40</td>
      </tr>
      <tr>
        <th scope="row">Tue</th>
        <td>132</td>
        <td>95</td>
        <td>35</td>
      </tr>
      <tr>
        <th scope="row">Wed</th>
        <td>101</td>
        <td>70</td>
        <td>45</td>
      </tr>
      <tr>
        <th scope="row">Thu</th>
        <td>134</td>
        <td>110</td>
        <td>38</td>
      </tr>
      <tr>
        <th scope="row">Fri</th>
        <td>90</td>
        <td>60</td>
        <td>42</td>
      </tr>
      <tr>
        <th scope="row">Sat</th>
        <td>230</td>
        <td>120</td>
        <td>55</td>
      </tr>
      <tr>
        <th scope="row">Sun</th>
        <td>210</td>
        <td>95</td>
        <td>48</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const channelTrafficStackedBarChartCanvas = document.getElementById(
    'channel-traffic-stacked-bar-chart',
  )

  new Chart(channelTrafficStackedBarChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      datasets: [
        {
          label: 'Organic',
          data: [120, 132, 101, 134, 90, 230, 210],
          backgroundColor: '#4f46e5',
          hoverBackgroundColor: '#4338ca',
          borderColor: '#ffffff',
          borderWidth: 2,
          maxBarThickness: 32,
        },
        {
          label: 'Paid',
          data: [80, 95, 70, 110, 60, 120, 95],
          backgroundColor: '#10b981',
          hoverBackgroundColor: '#059669',
          borderColor: '#ffffff',
          borderWidth: 2,
          maxBarThickness: 32,
        },
        {
          label: 'Referral',
          data: [40, 35, 45, 38, 42, 55, 48],
          backgroundColor: '#f59e0b',
          hoverBackgroundColor: '#d97706',
          borderColor: '#ffffff',
          borderWidth: 2,
          maxBarThickness: 32,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: ${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        x: {
          stacked: true,
          grid: { display: false },
          ticks: { color: '#4b5563' },
        },
        y: {
          stacked: true,
          beginAtZero: true,
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Traffic by channel</h2>

  <div class="mt-4 h-64">
    <canvas
      id="channel-traffic-stacked-bar-chart"
      role="img"
      aria-label="Traffic by channel, stacked bar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Website traffic by channel, per day
    </caption>
    <thead>
      <tr>
        <th scope="col">Day</th>
        <th scope="col">Organic</th>
        <th scope="col">Paid</th>
        <th scope="col">Referral</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Mon</th>
        <td>120</td>
        <td>80</td>
        <td>40</td>
      </tr>
      <tr>
        <th scope="row">Tue</th>
        <td>132</td>
        <td>95</td>
        <td>35</td>
      </tr>
      <tr>
        <th scope="row">Wed</th>
        <td>101</td>
        <td>70</td>
        <td>45</td>
      </tr>
      <tr>
        <th scope="row">Thu</th>
        <td>134</td>
        <td>110</td>
        <td>38</td>
      </tr>
      <tr>
        <th scope="row">Fri</th>
        <td>90</td>
        <td>60</td>
        <td>42</td>
      </tr>
      <tr>
        <th scope="row">Sat</th>
        <td>230</td>
        <td>120</td>
        <td>55</td>
      </tr>
      <tr>
        <th scope="row">Sun</th>
        <td>210</td>
        <td>95</td>
        <td>48</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const channelTrafficStackedBarChartCanvas = document.getElementById(
    'channel-traffic-stacked-bar-chart',
  )

  new Chart(channelTrafficStackedBarChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      datasets: [
        {
          label: 'Organic',
          data: [120, 132, 101, 134, 90, 230, 210],
          backgroundColor: '#818cf8',
          hoverBackgroundColor: '#a5b4fc',
          borderColor: '#111827',
          borderWidth: 2,
          maxBarThickness: 32,
        },
        {
          label: 'Paid',
          data: [80, 95, 70, 110, 60, 120, 95],
          backgroundColor: '#34d399',
          hoverBackgroundColor: '#6ee7b7',
          borderColor: '#111827',
          borderWidth: 2,
          maxBarThickness: 32,
        },
        {
          label: 'Referral',
          data: [40, 35, 45, 38, 42, 55, 48],
          backgroundColor: '#fbbf24',
          hoverBackgroundColor: '#fcd34d',
          borderColor: '#111827',
          borderWidth: 2,
          maxBarThickness: 32,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: ${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        x: {
          stacked: true,
          grid: { display: false },
          ticks: { color: '#9ca3af' },
        },
        y: {
          stacked: true,
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Revenue vs target</h2>

  <div class="mt-4 h-64">
    <canvas
      id="revenue-target-combo-chart"
      role="img"
      aria-label="Revenue vs target, combo chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue against quarterly target
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
        <th scope="col">Target</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
        <td>$40,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
        <td>$40,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
        <td>$40,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueTargetComboChartCanvas = document.getElementById('revenue-target-combo-chart')

  new Chart(revenueTargetComboChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          type: 'bar',
          label: 'Revenue',
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          backgroundColor: '#4f46e5',
          hoverBackgroundColor: '#4338ca',
          borderRadius: 4,
          maxBarThickness: 32,
          order: 2,
        },
        {
          type: 'line',
          label: 'Target',
          data: [32000, 32000, 32000, 40000, 40000, 40000],
          borderColor: '#f59e0b',
          backgroundColor: '#f59e0b',
          borderWidth: 2,
          borderDash: [6, 4],
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#f59e0b',
          pointHoverBorderColor: '#ffffff',
          pointHoverBorderWidth: 2,
          tension: 0,
          fill: false,
          order: 1,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${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`,
          },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Revenue vs target</h2>

  <div class="mt-4 h-64">
    <canvas
      id="revenue-target-combo-chart"
      role="img"
      aria-label="Revenue vs target, combo chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue against quarterly target
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">Revenue</th>
        <th scope="col">Target</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
        <td>$32,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
        <td>$40,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
        <td>$40,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
        <td>$40,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const revenueTargetComboChartCanvas = document.getElementById('revenue-target-combo-chart')

  new Chart(revenueTargetComboChartCanvas, {
    type: 'bar',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          type: 'bar',
          label: 'Revenue',
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          backgroundColor: '#818cf8',
          hoverBackgroundColor: '#a5b4fc',
          borderRadius: 4,
          maxBarThickness: 32,
          order: 2,
        },
        {
          type: 'line',
          label: 'Target',
          data: [32000, 32000, 32000, 40000, 40000, 40000],
          borderColor: '#fbbf24',
          backgroundColor: '#fbbf24',
          borderWidth: 2,
          borderDash: [6, 4],
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#fbbf24',
          pointHoverBorderColor: '#111827',
          pointHoverBorderWidth: 2,
          tension: 0,
          fill: false,
          order: 1,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        x: {
          grid: { display: false },
          ticks: { color: '#9ca3af' },
        },
        y: {
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: {
            color: '#9ca3af',
            callback: (tickValue) => `$${Number(tickValue) / 1000}k`,
          },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Revenue: this year vs last year</h2>

  <div class="mt-4 h-64">
    <canvas
      id="yearly-revenue-comparison-line-chart"
      role="img"
      aria-label="Revenue this year vs last year, line chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue, this year vs last year
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">This year</th>
        <th scope="col">Last year</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
        <td>$22,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
        <td>$25,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
        <td>$24,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
        <td>$29,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
        <td>$31,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
        <td>$35,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const yearlyRevenueComparisonLineChartCanvas = document.getElementById(
    'yearly-revenue-comparison-line-chart',
  )

  new Chart(yearlyRevenueComparisonLineChartCanvas, {
    type: 'line',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          label: 'This year',
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          borderColor: '#4f46e5',
          backgroundColor: 'transparent',
          borderWidth: 2,
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#4f46e5',
          pointHoverBorderColor: '#ffffff',
          pointHoverBorderWidth: 2,
          tension: 0.35,
          fill: false,
        },
        {
          label: 'Last year',
          data: [22000, 25000, 24000, 29000, 31000, 35000],
          borderColor: '#9ca3af',
          backgroundColor: 'transparent',
          borderWidth: 2,
          borderDash: [6, 4],
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#9ca3af',
          pointHoverBorderColor: '#ffffff',
          pointHoverBorderWidth: 2,
          tension: 0.35,
          fill: false,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${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`,
          },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Revenue: this year vs last year</h2>

  <div class="mt-4 h-64">
    <canvas
      id="yearly-revenue-comparison-line-chart"
      role="img"
      aria-label="Revenue this year vs last year, line chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Monthly revenue, this year vs last year
    </caption>
    <thead>
      <tr>
        <th scope="col">Month</th>
        <th scope="col">This year</th>
        <th scope="col">Last year</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Jan</th>
        <td>$28,000</td>
        <td>$22,000</td>
      </tr>
      <tr>
        <th scope="row">Feb</th>
        <td>$34,000</td>
        <td>$25,000</td>
      </tr>
      <tr>
        <th scope="row">Mar</th>
        <td>$31,000</td>
        <td>$24,000</td>
      </tr>
      <tr>
        <th scope="row">Apr</th>
        <td>$39,000</td>
        <td>$29,000</td>
      </tr>
      <tr>
        <th scope="row">May</th>
        <td>$42,000</td>
        <td>$31,000</td>
      </tr>
      <tr>
        <th scope="row">Jun</th>
        <td>$48,000</td>
        <td>$35,000</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const yearlyRevenueComparisonLineChartCanvas = document.getElementById(
    'yearly-revenue-comparison-line-chart',
  )

  new Chart(yearlyRevenueComparisonLineChartCanvas, {
    type: 'line',
    data: {
      labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
      datasets: [
        {
          label: 'This year',
          data: [28000, 34000, 31000, 39000, 42000, 48000],
          borderColor: '#818cf8',
          backgroundColor: 'transparent',
          borderWidth: 2,
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#818cf8',
          pointHoverBorderColor: '#111827',
          pointHoverBorderWidth: 2,
          tension: 0.35,
          fill: false,
        },
        {
          label: 'Last year',
          data: [22000, 25000, 24000, 29000, 31000, 35000],
          borderColor: '#9ca3af',
          backgroundColor: 'transparent',
          borderWidth: 2,
          borderDash: [6, 4],
          pointRadius: 0,
          pointHoverRadius: 5,
          pointHoverBackgroundColor: '#9ca3af',
          pointHoverBorderColor: '#111827',
          pointHoverBorderWidth: 2,
          tension: 0.35,
          fill: false,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        mode: 'index',
        intersect: false,
      },
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        x: {
          grid: { display: false },
          ticks: { color: '#9ca3af' },
        },
        y: {
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: {
            color: '#9ca3af',
            callback: (tickValue) => `$${Number(tickValue) / 1000}k`,
          },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Team performance</h2>

  <div class="mt-4 h-64">
    <canvas
      id="team-performance-radar-chart"
      role="img"
      aria-label="Team performance, radar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Team performance by metric
    </caption>
    <thead>
      <tr>
        <th scope="col">Metric</th>
        <th scope="col">Team A</th>
        <th scope="col">Team B</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Speed</th>
        <td>80</td>
        <td>65</td>
      </tr>
      <tr>
        <th scope="row">Quality</th>
        <td>90</td>
        <td>75</td>
      </tr>
      <tr>
        <th scope="row">Collaboration</th>
        <td>70</td>
        <td>88</td>
      </tr>
      <tr>
        <th scope="row">Innovation</th>
        <td>60</td>
        <td>92</td>
      </tr>
      <tr>
        <th scope="row">Reliability</th>
        <td>85</td>
        <td>70</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const teamPerformanceRadarChartCanvas = document.getElementById(
    'team-performance-radar-chart',
  )

  new Chart(teamPerformanceRadarChartCanvas, {
    type: 'radar',
    data: {
      labels: ['Speed', 'Quality', 'Collaboration', 'Innovation', 'Reliability'],
      datasets: [
        {
          label: 'Team A',
          data: [80, 90, 70, 60, 85],
          borderColor: '#4f46e5',
          backgroundColor: 'rgba(79, 70, 229, 0.2)',
          pointBackgroundColor: '#4f46e5',
          pointBorderColor: '#ffffff',
          pointHoverRadius: 5,
          borderWidth: 2,
        },
        {
          label: 'Team B',
          data: [65, 75, 88, 92, 70],
          borderColor: '#10b981',
          backgroundColor: 'rgba(16, 185, 129, 0.2)',
          pointBackgroundColor: '#10b981',
          pointBorderColor: '#ffffff',
          pointHoverRadius: 5,
          borderWidth: 2,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: ${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        r: {
          beginAtZero: true,
          max: 100,
          angleLines: { color: '#e5e7eb' },
          grid: { color: '#e5e7eb' },
          pointLabels: { color: '#4b5563', font: { size: 11 } },
          ticks: { display: false },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Team performance</h2>

  <div class="mt-4 h-64">
    <canvas
      id="team-performance-radar-chart"
      role="img"
      aria-label="Team performance, radar chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Team performance by metric
    </caption>
    <thead>
      <tr>
        <th scope="col">Metric</th>
        <th scope="col">Team A</th>
        <th scope="col">Team B</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Speed</th>
        <td>80</td>
        <td>65</td>
      </tr>
      <tr>
        <th scope="row">Quality</th>
        <td>90</td>
        <td>75</td>
      </tr>
      <tr>
        <th scope="row">Collaboration</th>
        <td>70</td>
        <td>88</td>
      </tr>
      <tr>
        <th scope="row">Innovation</th>
        <td>60</td>
        <td>92</td>
      </tr>
      <tr>
        <th scope="row">Reliability</th>
        <td>85</td>
        <td>70</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const teamPerformanceRadarChartCanvas = document.getElementById(
    'team-performance-radar-chart',
  )

  new Chart(teamPerformanceRadarChartCanvas, {
    type: 'radar',
    data: {
      labels: ['Speed', 'Quality', 'Collaboration', 'Innovation', 'Reliability'],
      datasets: [
        {
          label: 'Team A',
          data: [80, 90, 70, 60, 85],
          borderColor: '#818cf8',
          backgroundColor: 'rgba(129, 140, 248, 0.25)',
          pointBackgroundColor: '#818cf8',
          pointBorderColor: '#111827',
          pointHoverRadius: 5,
          borderWidth: 2,
        },
        {
          label: 'Team B',
          data: [65, 75, 88, 92, 70],
          borderColor: '#34d399',
          backgroundColor: 'rgba(52, 211, 153, 0.25)',
          pointBackgroundColor: '#34d399',
          pointBorderColor: '#111827',
          pointHoverRadius: 5,
          borderWidth: 2,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: ${tooltipItem.formattedValue}`,
          },
        },
      },
      scales: {
        r: {
          beginAtZero: true,
          max: 100,
          angleLines: { color: 'rgba(255, 255, 255, 0.1)' },
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          pointLabels: { color: '#9ca3af', font: { size: 11 } },
          ticks: { display: false },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Traffic sources</h2>

  <div class="mt-4 h-64">
    <canvas
      id="traffic-sources-polar-area-chart"
      role="img"
      aria-label="Traffic sources, polar area chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Traffic by source
    </caption>
    <thead>
      <tr>
        <th scope="col">Source</th>
        <th scope="col">Percentage</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Organic</th>
        <td>45%</td>
      </tr>
      <tr>
        <th scope="row">Paid</th>
        <td>25%</td>
      </tr>
      <tr>
        <th scope="row">Referral</th>
        <td>18%</td>
      </tr>
      <tr>
        <th scope="row">Direct</th>
        <td>12%</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const trafficSourcesPolarAreaChartCanvas = document.getElementById(
    'traffic-sources-polar-area-chart',
  )

  new Chart(trafficSourcesPolarAreaChartCanvas, {
    type: 'polarArea',
    data: {
      labels: ['Organic', 'Paid', 'Referral', 'Direct'],
      datasets: [
        {
          data: [45, 25, 18, 12],
          backgroundColor: [
            'rgba(79, 70, 229, 0.7)',
            'rgba(16, 185, 129, 0.7)',
            'rgba(245, 158, 11, 0.7)',
            'rgba(244, 63, 94, 0.7)',
          ],
          hoverBackgroundColor: ['#4f46e5', '#10b981', '#f59e0b', '#f43f5e'],
          borderColor: '#ffffff',
          borderWidth: 2,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) => `${tooltipItem.label}: ${tooltipItem.formattedValue}%`,
          },
        },
      },
      scales: {
        r: {
          beginAtZero: true,
          angleLines: { color: '#e5e7eb' },
          grid: { color: '#e5e7eb' },
          ticks: { display: false },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Traffic sources</h2>

  <div class="mt-4 h-64">
    <canvas
      id="traffic-sources-polar-area-chart"
      role="img"
      aria-label="Traffic sources, polar area chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Traffic by source
    </caption>
    <thead>
      <tr>
        <th scope="col">Source</th>
        <th scope="col">Percentage</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Organic</th>
        <td>45%</td>
      </tr>
      <tr>
        <th scope="row">Paid</th>
        <td>25%</td>
      </tr>
      <tr>
        <th scope="row">Referral</th>
        <td>18%</td>
      </tr>
      <tr>
        <th scope="row">Direct</th>
        <td>12%</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const trafficSourcesPolarAreaChartCanvas = document.getElementById(
    'traffic-sources-polar-area-chart',
  )

  new Chart(trafficSourcesPolarAreaChartCanvas, {
    type: 'polarArea',
    data: {
      labels: ['Organic', 'Paid', 'Referral', 'Direct'],
      datasets: [
        {
          data: [45, 25, 18, 12],
          backgroundColor: [
            'rgba(129, 140, 248, 0.7)',
            'rgba(52, 211, 153, 0.7)',
            'rgba(251, 191, 36, 0.7)',
            'rgba(251, 113, 133, 0.7)',
          ],
          hoverBackgroundColor: ['#818cf8', '#34d399', '#fbbf24', '#fb7185'],
          borderColor: '#111827',
          borderWidth: 2,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) => `${tooltipItem.label}: ${tooltipItem.formattedValue}%`,
          },
        },
      },
      scales: {
        r: {
          beginAtZero: true,
          angleLines: { color: 'rgba(255, 255, 255, 0.1)' },
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { display: false },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Ad spend vs conversions</h2>

  <div class="mt-4 h-64">
    <canvas
      id="ad-spend-conversions-scatter-chart"
      role="img"
      aria-label="Ad spend vs conversions, scatter chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Ad spend and conversions per campaign
    </caption>
    <thead>
      <tr>
        <th scope="col">Spend ($)</th>
        <th scope="col">Conversions</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">90</th>
        <td>8</td>
      </tr>
      <tr>
        <th scope="row">120</th>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">140</th>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">150</th>
        <td>15</td>
      </tr>
      <tr>
        <th scope="row">180</th>
        <td>18</td>
      </tr>
      <tr>
        <th scope="row">200</th>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">220</th>
        <td>25</td>
      </tr>
      <tr>
        <th scope="row">260</th>
        <td>30</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const adSpendConversionsScatterChartCanvas = document.getElementById(
    'ad-spend-conversions-scatter-chart',
  )

  new Chart(adSpendConversionsScatterChartCanvas, {
    type: 'scatter',
    data: {
      datasets: [
        {
          label: 'Campaigns',
          data: [
            { x: 90, y: 8 },
            { x: 120, y: 12 },
            { x: 140, y: 14 },
            { x: 150, y: 15 },
            { x: 180, y: 18 },
            { x: 200, y: 22 },
            { x: 220, y: 25 },
            { x: 260, y: 30 },
          ],
          backgroundColor: '#4f46e5',
          hoverBackgroundColor: '#4338ca',
          pointRadius: 5,
          pointHoverRadius: 7,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `$${tooltipItem.raw.x} spend → ${tooltipItem.raw.y} conversions`,
          },
        },
      },
      scales: {
        x: {
          title: { display: true, text: 'Spend ($)', color: '#4b5563' },
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
        y: {
          title: { display: true, text: 'Conversions', color: '#4b5563' },
          beginAtZero: true,
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Ad spend vs conversions</h2>

  <div class="mt-4 h-64">
    <canvas
      id="ad-spend-conversions-scatter-chart"
      role="img"
      aria-label="Ad spend vs conversions, scatter chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Ad spend and conversions per campaign
    </caption>
    <thead>
      <tr>
        <th scope="col">Spend ($)</th>
        <th scope="col">Conversions</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">90</th>
        <td>8</td>
      </tr>
      <tr>
        <th scope="row">120</th>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">140</th>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">150</th>
        <td>15</td>
      </tr>
      <tr>
        <th scope="row">180</th>
        <td>18</td>
      </tr>
      <tr>
        <th scope="row">200</th>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">220</th>
        <td>25</td>
      </tr>
      <tr>
        <th scope="row">260</th>
        <td>30</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const adSpendConversionsScatterChartCanvas = document.getElementById(
    'ad-spend-conversions-scatter-chart',
  )

  new Chart(adSpendConversionsScatterChartCanvas, {
    type: 'scatter',
    data: {
      datasets: [
        {
          label: 'Campaigns',
          data: [
            { x: 90, y: 8 },
            { x: 120, y: 12 },
            { x: 140, y: 14 },
            { x: 150, y: 15 },
            { x: 180, y: 18 },
            { x: 200, y: 22 },
            { x: 220, y: 25 },
            { x: 260, y: 30 },
          ],
          backgroundColor: '#818cf8',
          hoverBackgroundColor: '#a5b4fc',
          pointRadius: 5,
          pointHoverRadius: 7,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `$${tooltipItem.raw.x} spend → ${tooltipItem.raw.y} conversions`,
          },
        },
      },
      scales: {
        x: {
          title: { display: true, text: 'Spend ($)', color: '#9ca3af' },
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
        y: {
          title: { display: true, text: 'Conversions', color: '#9ca3af' },
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-200 bg-white p-6">
  <h2 class="text-sm font-medium text-gray-900">Campaign performance</h2>

  <div class="mt-4 h-64">
    <canvas
      id="campaign-performance-bubble-chart"
      role="img"
      aria-label="Campaign performance, bubble chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Campaign spend, conversions, and reach
    </caption>
    <thead>
      <tr>
        <th scope="col">Campaign</th>
        <th scope="col">Spend ($)</th>
        <th scope="col">Conversions</th>
        <th scope="col">Reach index</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Search</th>
        <td>3,200</td>
        <td>18,000</td>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">Social</th>
        <td>2,400</td>
        <td>9,500</td>
        <td>16</td>
      </tr>
      <tr>
        <th scope="row">Display</th>
        <td>1,800</td>
        <td>5,200</td>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">Email</th>
        <td>900</td>
        <td>7,800</td>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">Video</th>
        <td>2,600</td>
        <td>6,100</td>
        <td>18</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const campaignPerformanceBubbleChartCanvas = document.getElementById(
    'campaign-performance-bubble-chart',
  )

  new Chart(campaignPerformanceBubbleChartCanvas, {
    type: 'bubble',
    data: {
      datasets: [
        {
          label: 'Search',
          data: [{ x: 3200, y: 18000, r: 22 }],
          backgroundColor: 'rgba(79, 70, 229, 0.7)',
          hoverBackgroundColor: '#4f46e5',
        },
        {
          label: 'Social',
          data: [{ x: 2400, y: 9500, r: 16 }],
          backgroundColor: 'rgba(16, 185, 129, 0.7)',
          hoverBackgroundColor: '#10b981',
        },
        {
          label: 'Display',
          data: [{ x: 1800, y: 5200, r: 12 }],
          backgroundColor: 'rgba(245, 158, 11, 0.7)',
          hoverBackgroundColor: '#f59e0b',
        },
        {
          label: 'Email',
          data: [{ x: 900, y: 7800, r: 14 }],
          backgroundColor: 'rgba(244, 63, 94, 0.7)',
          hoverBackgroundColor: '#f43f5e',
        },
        {
          label: 'Video',
          data: [{ x: 2600, y: 6100, r: 18 }],
          backgroundColor: 'rgba(14, 165, 233, 0.7)',
          hoverBackgroundColor: '#0ea5e9',
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#4b5563' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${tooltipItem.raw.x} spend, ${tooltipItem.raw.y} conversions`,
          },
        },
      },
      scales: {
        x: {
          title: { display: true, text: 'Spend ($)', color: '#4b5563' },
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
        y: {
          title: { display: true, text: 'Conversions', color: '#4b5563' },
          beginAtZero: true,
          grid: { color: '#e5e7eb' },
          ticks: { color: '#4b5563' },
        },
      },
    },
  })
</script>

Plugins: chart.js

<div class="rounded-lg border border-gray-800 bg-gray-900 p-6">
  <h2 class="text-sm font-medium text-white">Campaign performance</h2>

  <div class="mt-4 h-64">
    <canvas
      id="campaign-performance-bubble-chart"
      role="img"
      aria-label="Campaign performance, bubble chart"
    ></canvas>
  </div>

  <table class="sr-only">
    <caption>
      Campaign spend, conversions, and reach
    </caption>
    <thead>
      <tr>
        <th scope="col">Campaign</th>
        <th scope="col">Spend ($)</th>
        <th scope="col">Conversions</th>
        <th scope="col">Reach index</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Search</th>
        <td>3,200</td>
        <td>18,000</td>
        <td>22</td>
      </tr>
      <tr>
        <th scope="row">Social</th>
        <td>2,400</td>
        <td>9,500</td>
        <td>16</td>
      </tr>
      <tr>
        <th scope="row">Display</th>
        <td>1,800</td>
        <td>5,200</td>
        <td>12</td>
      </tr>
      <tr>
        <th scope="row">Email</th>
        <td>900</td>
        <td>7,800</td>
        <td>14</td>
      </tr>
      <tr>
        <th scope="row">Video</th>
        <td>2,600</td>
        <td>6,100</td>
        <td>18</td>
      </tr>
    </tbody>
  </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script>
  const campaignPerformanceBubbleChartCanvas = document.getElementById(
    'campaign-performance-bubble-chart',
  )

  new Chart(campaignPerformanceBubbleChartCanvas, {
    type: 'bubble',
    data: {
      datasets: [
        {
          label: 'Search',
          data: [{ x: 3200, y: 18000, r: 22 }],
          backgroundColor: 'rgba(129, 140, 248, 0.7)',
          hoverBackgroundColor: '#818cf8',
        },
        {
          label: 'Social',
          data: [{ x: 2400, y: 9500, r: 16 }],
          backgroundColor: 'rgba(52, 211, 153, 0.7)',
          hoverBackgroundColor: '#34d399',
        },
        {
          label: 'Display',
          data: [{ x: 1800, y: 5200, r: 12 }],
          backgroundColor: 'rgba(251, 191, 36, 0.7)',
          hoverBackgroundColor: '#fbbf24',
        },
        {
          label: 'Email',
          data: [{ x: 900, y: 7800, r: 14 }],
          backgroundColor: 'rgba(251, 113, 133, 0.7)',
          hoverBackgroundColor: '#fb7185',
        },
        {
          label: 'Video',
          data: [{ x: 2600, y: 6100, r: 18 }],
          backgroundColor: 'rgba(56, 189, 248, 0.7)',
          hoverBackgroundColor: '#38bdf8',
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: 'bottom',
          labels: { color: '#9ca3af' },
        },
        tooltip: {
          callbacks: {
            label: (tooltipItem) =>
              `${tooltipItem.dataset.label}: $${tooltipItem.raw.x} spend, ${tooltipItem.raw.y} conversions`,
          },
        },
      },
      scales: {
        x: {
          title: { display: true, text: 'Spend ($)', color: '#9ca3af' },
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
        y: {
          title: { display: true, text: 'Conversions', color: '#9ca3af' },
          beginAtZero: true,
          grid: { color: 'rgba(255, 255, 255, 0.1)' },
          ticks: { color: '#9ca3af' },
        },
      },
    },
  })
</script>

Plugins: chart.js