Bar Chart
Grouped or stacked bars for comparing categories across series
<div id="my-chart" class="nds-chart"></div>
NDS.Chart.create('#my-chart', {
type: 'bar',
series: [
{ name: 'Completed', data: [12, 18, 15, 22, 28, 20] },
{ name: 'In Progress', data: [8, 10, 14, 9, 12, 15] },
{ name: 'Pending', data: [5, 7, 6, 4, 3, 8] },
],
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
height: 350, // Chart height (px)
bar: {
stacked: false, // Stack series on top of each other
borderRadius: 6, // Corner radius for bar tops
gap: 0.3, // Gap between groups (0–1)
},
dataLabels: { show: true, format: '%' }, // Show values above bars (suffix)
grid: { show: true }, // Horizontal gridlines
yaxis: { show: true, title: '' }, // Y-axis labels & title
xaxis: { show: true, title: '' }, // X-axis labels & title
legend: { show: true, position: 'top' },
tooltip: { show: true },
// colors: ['#1B8354', '#54C08A'], // Optional palette override
});
Line Chart
Smooth or straight lines for tracking trends over time, with optional area fill
<div id="my-chart" class="nds-chart"></div>
NDS.Chart.create('#my-chart', {
type: 'line',
series: [
{ name: 'Sessions', data: [10, 41, 35, 51, 49, 62, 69, 91, 80] },
{ name: 'Page Views', data: [23, 42, 35, 27, 43, 22, 17, 31, 48] },
],
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
height: 350, // Chart height (px)
line: {
smooth: true, // Catmull-Rom curves (false = straight)
dots: true, // Show data point circles
dotRadius: 4, // Dot radius (px)
width: 2, // Line stroke width (px)
area: false, // Fill area under lines
},
grid: { show: true }, // Horizontal gridlines
yaxis: { show: true, title: 'Active users' },
xaxis: { show: true, title: 'Month' },
legend: { show: true, position: 'top' },
tooltip: { show: true },
});
Dense X-Axis Labels
Labels auto-rotate to 45° when they would overlap. Opt into decimation to show only every Nth label for very dense time-series data
NDS.Chart.create('#my-chart', {
type: 'line',
series: [{ name: 'Sessions', data: [/* 24 values */] }],
labels: ['Jan 23', 'Feb 23', /* … */, 'Dec 24'],
xaxis: {
labelRotate: 'auto', // 'auto' | 0 | 45 | 90 | <number>
labelDecimate: false, // false | true | 'auto' | <number>
},
});
Pie Chart
Proportional segments for showing distribution of a whole
<div id="my-chart" class="nds-chart"></div>
// Pie: series are plain numbers, not objects
NDS.Chart.create('#my-chart', {
type: 'pie',
series: [44, 55, 13, 43],
labels: ['Services', 'Products', 'Support', 'Other'],
height: 300, // Chart size (px)
startAngle: 0, // Starting angle (degrees)
stroke: {
show: false, // Stroke between slices
width: 2, // Stroke width
color: '#fff', // Stroke color
},
dataLabels: { show: true }, // Percentage labels on slices
legend: { show: true, position: 'bottom' },
tooltip: { show: true },
});
Donut Chart
Pie chart with an inner hole for a cleaner look or center content
<div id="my-chart" class="nds-chart"></div>
// Donut: same as pie, with donut.size for inner hole
NDS.Chart.create('#my-chart', {
type: 'donut',
series: [35, 25, 20, 20],
labels: ['Completed', 'In Progress', 'Review', 'Pending'],
height: 300,
donut: {
size: 0.5, // Inner hole ratio (0–1)
},
startAngle: 0,
stroke: {
show: false, // Stroke between slices
width: 2,
color: '#fff',
},
dataLabels: { show: true },
legend: { show: true, position: 'bottom' },
tooltip: { show: true },
});
HTML Initialization
Charts can also be initialized declaratively using data attributes
<div class="nds-chart"
data-chart-type="bar"
data-chart-series='[{"name":"Q1","data":[30,40,35]},{"name":"Q2","data":[50,30,45]}]'
data-chart-labels='["Jan","Feb","Mar"]'>
</div>
Theming
Override CSS custom properties to customize chart colors without changing JavaScript options
<div id="my-chart" class="nds-chart my-chart"></div>
.my-chart {
--chart-color-1: #6366F1;
--chart-color-2: #A78BFA;
--chart-color-3: #C4B5FD;
}
Built-in Features
Charts with data-chart-* attributes initialize on page load. Call NDS.Chart.init() to re-scan after adding new chart elements dynamically.
Charts resize automatically when their container width changes. No manual resize calls needed.
Override colors, grid, tooltips, and labels with CSS custom properties. Dark mode adapts automatically.
Automatic nice-number axis scaling, number formatting (K/M suffixes), and legend wrapping.
Tooltips hidden in print, transitions disabled for reduced-motion preference. SVG output includes ARIA labels for screen readers.
Create, update, and destroy charts with NDS.Chart.create(). Options deep-merge on update for live reconfiguration.
Usage Guidelines
Best Practices
- Use bar charts for comparing discrete categories or tracking changes across periods. Use stacked mode when the total matters as much as individual values
- Use line charts for continuous data, trends, and time series. Enable area fill to emphasize volume over shape
- Use pie or donut charts for showing proportions of a whole. Keep to 6 or fewer segments so the chart stays readable
- Avoid pie charts when differences between segments are small. A bar chart makes small differences easier to compare
- For a headline number with a trend sparkline, use a Metric tile instead of a standalone chart
- Use HTML
data-chart-*attributes for static charts that don't change. Use the JS API for dynamic or user-driven data that updates after load - Set axis titles (
yaxis.title,xaxis.title) to label what the numbers represent. Without titles, the chart relies on the legend alone - Override
--chart-color-*properties to match your project's brand palette. The default palette uses Saudi flag green tones - Charts auto-resize via ResizeObserver. No manual resize calls are needed when the container width changes
- X-axis labels auto-rotate to 45° when they would overlap (
xaxis.labelRotate: 'auto'by default). For dense time-series, opt intoxaxis.labelDecimate: 'auto'to show only every Nth label instead
Methods
| Method | Description |
|---|---|
NDS.Chart.create(el, opts) |
Create a chart on an element (accepts selector string or DOM element) |
NDS.Chart.init() |
Auto-initialize all .nds-chart elements with data attributes |
chart.update(opts) |
Update chart with new options (merges with existing) and re-render |
chart.destroy() |
Remove chart, clean up listeners and observers |
Common Options
| Option | Type | Default | Description |
|---|---|---|---|
type |
string | 'bar' |
'bar', 'line', 'pie', or 'donut' |
series |
array | required | Data series. Objects with name/data for bar/line, numbers for pie/donut |
labels |
array | required | Category labels for x-axis or pie slice names |
height |
number | 350/300 | Chart height in pixels (350 for bar/line, 300 for pie/donut) |
colors |
array | CSS vars | Override color palette with hex/rgb values |
legend.show |
boolean | true | Show/hide legend |
legend.position |
string | 'top'/'bottom' |
'top' for bar/line, 'bottom' for pie/donut |
tooltip.show |
boolean | true | Show/hide hover tooltips |
padding |
object | auto | Override plot padding per side: { top, bottom, left, right } in pixels. Defaults are picked from the axis layout (top 20, bottom 40, sides 20 or 55 depending on whether yaxis.show is true). Set { top: 0, bottom: 0, left: 0, right: 0 } for edge-to-edge sparklines. |
direction |
string | auto | 'ltr' or 'rtl' to force a reading direction. Default reads the chart's computed CSS direction, which honors any dir="..." attribute or direction: CSS rule on an ancestor. |
Bar Options
| Option | Type | Default | Description |
|---|---|---|---|
bar.stacked |
boolean | false | Stack bars on top of each other |
bar.borderRadius |
number | 6 | Corner radius for bar tops |
bar.gap |
number | 0.3 | Gap ratio between groups (0-1) |
dataLabels.show |
boolean | false | Show value labels above bars |
dataLabels.format |
string | function | none | Append a suffix to values: '%' turns 75 into "75%". For custom logic, pass a function: v => v + ' SAR'. Applied to data labels, Y-axis labels, and tooltips |
Line Options
| Option | Type | Default | Description |
|---|---|---|---|
line.smooth |
boolean | true | Smooth curves (Catmull-Rom) vs straight segments |
line.dots |
boolean | true | Show data point dots |
line.dotRadius |
number | 4 | Dot radius in pixels |
line.width |
number | 2 | Line stroke width |
line.area |
boolean | false | Fill area under lines |
line.crosshair |
boolean | true | Vertical hover line that snaps to the nearest data point and enlarges its dot. Disable to fall back to per-dot hover tooltips. |
line.spotlight |
number | string | none | Persistent highlight on a single data point: numeric index, 'first', or 'last'. Renders a translucent halo and enlarges the dot at that position. Used by the Metric tile to anchor the comparison value. |
Axis Options (bar + line)
| Option | Type | Default | Description |
|---|---|---|---|
grid.show |
boolean | true | Show horizontal gridlines |
yaxis.show |
boolean | true | Show y-axis value labels |
yaxis.title |
string | '' |
Y-axis title (rendered vertically) |
xaxis.show |
boolean | true | Show x-axis category labels |
xaxis.title |
string | '' |
X-axis title |
xaxis.labelRotate |
string | number | 'auto' |
Rotate x-axis labels when they would overlap. 'auto' picks 0° or 45° based on fit; pass an explicit number (e.g. 45 or 90) to force an angle. Mirrored in RTL |
xaxis.labelDecimate |
boolean | string | number | false |
Show only every Nth label to thin out dense axes (time-series). true or 'auto' computes the step from available width; pass a number (e.g. 3) to force every-Nth |
Pie / Donut Options
| Option | Type | Default | Description |
|---|---|---|---|
donut.size |
number | 0.5 | Inner hole ratio (0-1, donut only) |
stroke.show |
boolean | false | Show stroke between slices |
stroke.width |
number | 2 | Stroke width |
stroke.color |
string | '#fff' |
Stroke color |
startAngle |
number | 0 | Starting angle in degrees |
Data Attributes
| Attribute | Description |
|---|---|
data-chart-type |
Chart type: bar, line, pie, or donut |
data-chart-series |
JSON array of series data. Objects with name and data for bar/line, plain numbers for pie/donut. |
data-chart-labels |
JSON array of category labels for x-axis or pie slice names. |
data-chart-config |
JSON object with full chart options. Overrides individual data attributes when both are present. |
CSS Custom Properties
| Property | Description |
|---|---|
--chart-color-1 to --chart-color-6 |
Series color palette (6 colors, auto-wraps beyond 6) |
--chart-grid-color |
Gridline color |
--chart-text |
Axis label and title color |
--chart-label |
Data label, legend, and tooltip text color |
--chart-radius |
Tooltip border radius |
--chart-area-opacity |
Area fill opacity for line charts |
--chart-tooltip-bg |
Tooltip background color |
--chart-tooltip-border |
Tooltip border color |
--chart-pie-label-1 to --chart-pie-label-6 |
Pie/donut percentage label color per slice |
--chart-dot-fill |
Line chart dot fill color |