Graph Component

SVG-based charts with zero configuration - line, bar, pie, donut and gauge from plain HTML data attributes

Live Demo

Line Chart

Data provided inline with data-props (JSON). Supports smooth curves, filled areas and per-series colors.

<div data-component="graph"
            data-props='{
            "type": "line",
            "curve": true,
            "fillArea": true,
            "data": [
            {"name": "2025", "color": "#3b82f6", "data": [
            {"label": "Jan", "value": 65}, {"label": "Feb", "value": 59},
            {"label": "Mar", "value": 80}, {"label": "Apr", "value": 81},
            {"label": "May", "value": 76}, {"label": "Jun", "value": 90}
            ]},
            {"name": "2024", "color": "#a855f7", "data": [
            {"label": "Jan", "value": 45}, {"label": "Feb", "value": 52},
            {"label": "Mar", "value": 58}, {"label": "Apr", "value": 61},
            {"label": "May", "value": 70}, {"label": "Jun", "value": 72}
            ]}
            ]
            }' style="height: 320px;">
            </div>

Bar Chart from HTML Table

Point data-table to any table ID - the data is read directly from the table below (no JavaScript needed).

Q1 Q2 Q3 Q4
Sales 120 150 135 180
Expenses 80 90 85 95
<table id="quarterly-table">
            <thead>
            <tr><th></th><th>Q1</th><th>Q2</th><th>Q3</th><th>Q4</th></tr>
            </thead>
            <tbody>
            <tr><th>Sales</th><td>120</td><td>150</td><td>135</td><td>180</td></tr>
            <tr><th>Expenses</th><td>80</td><td>90</td><td>85</td><td>95</td></tr>
            </tbody>
            </table>

            <!-- Renders a bar chart from the table above -->
            <div data-component="graph"
            data-type="bar"
            data-table="quarterly-table"
            style="height: 320px;">
            </div>

Pie Chart

Shows proportions with data labels. Use data-show-value-instead-of-percent to toggle between values and percentages.

<div data-component="graph"
            data-type="pie"
            data-show-value-instead-of-percent="false"
            data-props='{
            "data": [
            {"name": "Traffic", "data": [
            {"label": "Desktop", "value": 45},
            {"label": "Mobile", "value": 38},
            {"label": "Tablet", "value": 10},
            {"label": "Others", "value": 7}
            ]}
            ]
            }' style="height: 320px;">
            </div>

Donut Chart

A ring chart with customizable thickness and center text - perfect for budgets and allocation.

<div data-component="graph"
            data-type="donut"
            data-donut-thickness="40"
            data-center-text="Budget"
            data-props='{
            "data": [
            {"name": "Budget", "data": [
            {"label": "Housing", "value": 30},
            {"label": "Food", "value": 25},
            {"label": "Savings", "value": 20},
            {"label": "Transport", "value": 15},
            {"label": "Others", "value": 10}
            ]}
            ]
            }' style="height: 320px;">
            </div>

Gauge Chart

A single value in a range - great for KPIs and scores. Takes one series with one data point.

<div data-component="graph"
            data-type="gauge"
            data-max-gauge-value="100"
            data-gauge-curve-width="24"
            data-props='{
            "data": [
            {"name": "Performance", "data": [
            {"label": "Score", "value": 78}
            ]}
            ]
            }' style="height: 260px;">
            </div>

Loading Data

From API URL

Set data-url to load data from a server endpoint. This chart fetches from api/sales.php which returns random values on every request.

<div data-component="graph"
            data-type="line"
            data-url="api/sales.php"
            style="height: 320px;">
            </div>

            <!-- Refresh manually from JavaScript -->
            <script>
            const element = document.querySelector('#url-graph');
            const instance = GraphComponent.getInstance(element);
            instance.refresh();
            </script>

Auto Refresh (Polling)

Set data-polling-interval (ms) together with data-url to reload automatically. This chart polls every 5 seconds - watch the values change.

<div data-component="graph"
            data-type="bar"
            data-url="api/sales.php"
            data-polling-interval="5000"
            style="height: 320px;">
            </div>

Event-based Refresh

Charts sharing the same data-refresh-event all refresh together when that event is emitted through the EventManager.

<!-- Both charts listen for the same event -->
            <div data-component="graph"
            data-type="line"
            data-url="api/sales.php"
            data-refresh-event="graph:refresh-demo">
            </div>
            <div data-component="graph"
            data-type="bar"
            data-url="api/sales.php"
            data-refresh-event="graph:refresh-demo">
            </div>

            <script>
            // Emitting the event refreshes every listener at once
            EventManager.emit('graph:refresh-demo');
            </script>

JavaScript API

This chart is created entirely from JavaScript. Use the controls to call the API methods - every action is logged in the event log below.

Event Log

  • Interact with the chart or buttons to see events...
// Create a graph entirely from JavaScript
                    const playground = await GraphComponent.create('#api-playground', {
                    type: 'line',
                    curve: true,
                    showLegend: true,
                    animation: true,
                    animationDuration: 800,
                    data: [
                    {name: 'Visitors', data: [
                    {label: 'Mon', value: 120},
                    {label: 'Tue', value: 150},
                    {label: 'Wed', value: 135}
                    ]}
                    ],

                    // Callbacks work too
                    onClick(dataPoint, seriesIndex) {
                    console.log('Clicked:', dataPoint.label, dataPoint.value);
                    },

                    onDataChange(data) {
                    console.log('Data updated:', data);
                    }
                    });

                    // Or grab an existing instance from an element / ID
                    const instance = GraphComponent.getInstance(element);
                    const same = GraphComponent.getInstance(instance.id);
// Replace the whole dataset
                    instance.setData([
                    {name: 'Visitors', data: [
                    {label: 'Mon', value: 200},
                    {label: 'Tue', value: 180},
                    {label: 'Wed', value: 220}
                    ]}
                    ]);

                    // Append a single point to a series (index 0 = first series)
                    instance.addDataPoint({label: 'Thu', value: 195}, 0);

                    // Switch chart type without recreating the chart
                    instance.setType('bar'); // line | bar | pie | donut | gauge

                    // Reload from the configured data-url (bypasses cache)
                    await instance.loadData();

                    // Refresh (same as loadData with force)
                    instance.refresh();

                    // Export as image (png, jpeg or svg)
                    instance.exportToImage('my-chart', 'png');

                    // Clean up when done
                    instance.destroy();
// DOM events are dispatched on the container element
                    const element = document.querySelector('#api-playground');

                    element.addEventListener('graph:created', e => {
                    console.log('Created:', e.detail.instance.id);
                    });

                    element.addEventListener('graph:loaded', e => {
                    console.log('Loaded from cache?', e.detail.fromCache);
                    });

                    element.addEventListener('graph:data-changed', e => {
                    console.log('New data:', e.detail.data);
                    });

                    element.addEventListener('graph:type-changed', e => {
                    console.log('Type changed to:', e.detail.type);
                    });

                    element.addEventListener('graph:error', e => {
                    console.error('Loading failed:', e.detail.error);
                    });

                    // The same events are also available through the EventManager
                    EventManager.on('graph:loaded', payload => {
                    console.log('Loaded:', payload.data);
                    });

Styling

Custom Colors & Legend Position

Pass a JSON array to data-colors for a custom palette and use data-legend-position (top, bottom, left, right) to place the legend.

<!-- Custom color palette -->
            <div data-component="graph"
            data-type="donut"
            data-colors='["#3b82f6", "#22c55e", "#f59e0b", "#ef4444"]'
            data-props='{...}'>
            </div>

            <!-- Legend on the right -->
            <div data-component="graph"
            data-type="line"
            data-legend-position="right"
            data-curve="true"
            data-props='{...}'>
            </div>

Grid & Axis Options

Toggle the grid and axis with data-show-grid and data-show-axis, or restyle everything through container CSS.

<div data-component="graph"
            data-type="line"
            data-curve="true"
            data-show-grid="false"
            data-show-axis="false"
            data-fill-area="true"
            data-props='{...}'>
            </div>

Key Features

Auto-initialization

Add data-component="graph" and the chart initializes itself - no JavaScript required.

5 Chart Types

Line, bar, pie, donut and gauge charts, all rendered as crisp SVG.

Multiple Data Sources

Inline data (data-props), HTML tables (data-table) or APIs (data-url).

Auto Refresh

Time-based polling and event-based refresh keep charts up to date.

Responsive

Charts redraw automatically when the container resizes.

Export

Export any chart as PNG, JPEG or SVG image with one call.

Interactive

Tooltips, legends and click handlers on every data point.

Event System

Rich lifecycle events via DOM events and the EventManager.

Configuration Options

Option Type Default Description
data-type string 'line' Chart type: line, bar, pie, donut, gauge
data-url string - API endpoint to load data from
data-table string - ID of an HTML table to read data from
data-props object - All options as inline JSON (including data)
data-colors array [...] Custom color palette (JSON array)
data-curve boolean true Smooth curve lines (line chart)
data-fill-area boolean false Fill the area under the line (line chart)
data-donut-thickness number 30 Ring thickness (donut chart)
data-max-gauge-value number 100 Maximum value of the gauge range (gauge chart)
data-gauge-curve-width number 30 Gauge arc thickness (gauge chart)
data-center-text string - Text in the center (donut/gauge)
data-show-grid boolean true Show grid lines
data-show-axis boolean true Show axis lines
data-show-legend boolean true Show legend
data-legend-position string 'bottom' Legend position: top, bottom, left, right
data-show-tooltip boolean true Show tooltips on hover
data-show-data-labels boolean true Show labels on data points
data-show-value-instead-of-percent boolean true Label style for pie/donut
data-animation boolean false Enable draw animation
data-animation-duration number 1000 Animation duration (ms)
data-polling-interval number 0 Auto reload interval in ms (0 = off)
data-refresh-event string - EventManager event(s) that trigger a refresh
data-cache boolean false Cache data-url responses
data-cache-time number 60000 Cache TTL in ms
data-max-data-points number 20 Maximum visible data points
data-autoload boolean true Load data on initialization

1. Declarative HTML

Every option can be set with data-* attributes. Values are parsed automatically - booleans, numbers, arrays and JSON objects all work.

2. Data Sources

Data comes from data-props, an HTML table via data-table, or a server endpoint via data-url - with optional caching.

3. SVG Rendering

The GraphRenderer draws pure SVG - sharp on every screen, themeable with CSS and exportable to image files.

4. Stays in Sync

ResizeObserver redraws on container changes, the MutationObserver picks up charts added to the DOM later, and locale changes trigger a refresh.

5. Events Everywhere

Each instance dispatches graph:* DOM events and mirrors them on the EventManager, so any part of your app can react.

6. Clean Lifecycle

Instances clean up their timers, observers and DOM references on destroy() - ready for SPA navigation.

Next Steps