Recently, I revamped my website to focus more on blogs. This included adding a search bar to enhance user navigation through my content. In this post, I’ll guide you through the process of adding your own interactive charts to an Astro project using ApexCharts!
Getting Started with ApexCharts
To kick things off, we’ll utilize the ChartsComponent which we’ve designed to render ApexCharts.
Below is a basic example illustrating how to incorporate a mixed chart:
The Charts Component
Installation
First, install ApexCharts and its type definitions:
# Using npm
npm install apexcharts @types/apexcharts
# Using yarn
yarn add apexcharts @types/apexcharts
Basic Setup
ApexCharts requires that each chart has a unique container ID to render correctly. If multiple charts are using the same ID (‘#chart’), they may interfere with each other.
You can modify the ChartsComponent.astro to accept an additional id property:
Create a new component file ChartsComponent.astro
:
---
// ChartsComponent.astro
interface Props {
chart: string;
chartId: string;
title?: string;
description?: string;
}
const { chart, chartId, title, description } = Astro.props;
---
<div class="chart-container w-full h-[400px] p-4 bg-white rounded-lg shadow-md">
{title && <h2 id={`${chartId}-title`} class="text-lg font-semibold mb-2">{title}</h2>}
{description && <p id={`${chartId}-desc`} class="text-sm text-gray-600 mb-4">{description}</p>}
<div
id={chartId}
role="img"
aria-labelledby={title ? `${chartId}-title` : undefined}
aria-describedby={description ? `${chartId}-desc` : undefined}
></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script is:inline define:vars={{ chartData: chart, chartId }}>
try {
const options = JSON.parse(chartData);
// Add default accessibility options
options.chart = {
...options.chart,
animations: {
enabled: true,
easing: 'easeinout',
speed: 800,
animateGradually: {
enabled: true,
delay: 150
},
dynamicAnimation: {
enabled: true,
speed: 350
}
},
accessibility: {
enabled: true,
announceNewData: {
enabled: true,
announcementPolicy: 'all'
}
}
};
document.addEventListener('DOMContentLoaded', function() {
const chart = new ApexCharts(document.querySelector(`#${chartId}`), options);
chart.render().catch(console.error);
});
} catch (error) {
console.error('Error rendering chart:', error);
document.querySelector(`#${chartId}`)?.insertAdjacentHTML(
'beforeend',
'<div class="text-red-500">Error rendering chart. Please check console for details.</div>'
);
}
</script>
<style>
.chart-container {
min-height: 400px;
/* Ensure contrast for accessibility */
--chart-background: theme('colors.white');
--chart-text: theme('colors.gray.900');
}
@media (prefers-reduced-motion: reduce) {
.chart-container {
--chart-animation-duration: 0s;
}
}
</style>
Functionality Breakdown
This component performs the following functions:
-
Accepts a chart configuration in string format as a prop.
- Example:
chart={JSON.stringify({ series: [{ name: 'TEAM A', type: 'column', data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 30] }, { name: 'TEAM B', type: 'area', data: [44, 55, 41, 67, 22, 43, 21, 41, 56, 27, 43] }, { name: 'TEAM C', type: 'line', data: [30, 25, 36, 30, 45, 35, 64, 52, 59, 36, 39] }], chart: { height: 350, type: 'line', stacked: false, } })}
- Example:
-
Utilizes Tailwind CSS classes for styling the container.
<div class="chart-container w-full h-[400px] p-4 bg-white rounded-lg shadow-md"> <div id={chartId}></div> </div>
-
Includes ApexCharts from a CDN for rendering.
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
-
Parses the chart configuration and creates the chart once the DOM is ready.
document.addEventListener('DOMContentLoaded', function() { const options = JSON.parse(chartData); const chart = new ApexCharts(document.querySelector(`#${chartId}`), options); chart.render(); });
Rendering Multiple Charts
<ChartsComponent
chartId="line-chart"
chart={`
{
"chart": {
"type": "line"
},
"series": [{
"name": "sales",
"data": [30, 40, 35, 50, 49, 60, 70, 91, 125]
}],
"xaxis": {
"categories": [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
}
}
`}
/>
When you render the **ChartsComponent, provide a unique ID for each chart:
Here’s is the end result: :D
Conclusion
And there you have it! :D
Adding interactive charts to your Astro project isn’t just a technical task; it’s a chance to make your data come alive and engage your visitors in a whole new way. I’ve loved integrating ApexCharts into my site, and I hope you found this guide helpfu.