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.

4/4 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="Line chart showing monthly revenue rising from $28,000 in January to $48,000 in June"
    ></canvas>
  </div>
</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 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`,
          },
        },
      },
    },
  })

  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()
    })
  })
</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="Line chart showing monthly revenue rising from $28,000 in January to $48,000 in June"
    ></canvas>
  </div>
</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 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="Bar chart showing orders per day this week, peaking at 32 orders on Saturday"
    ></canvas>
  </div>
</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="Bar chart showing orders per day this week, peaking at 32 orders on Saturday"
    ></canvas>
  </div>
</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="Donut chart showing 68% of orders paid, 22% pending, and 10% refunded"
    ></canvas>
  </div>
</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="Donut chart showing 68% of orders paid, 22% pending, and 10% refunded"
    ></canvas>
  </div>
</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="Sparkline showing monthly revenue trending upward"
    ></canvas>
  </div>
</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="Sparkline showing monthly revenue trending upward"
    ></canvas>
  </div>
</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