Sand.js is a lightweight, framework-agnostic JavaScript library for building sunburst charts using SVG.
It is fully data-driven: you describe your chart in JSON, and Sand.js takes care of both layout computation and rendering.
Sand.js is designed to be:
- Lightweight: no heavy dependencies.
- Agnostic: works with plain HTML, or in any framework.
- JSON-driven: describe your sunburst once, render anywhere.
- Accessible: interactive charts with sensible defaults.
Term | Description |
---|---|
Sunburst | The entire chart, composed of one or more layers. |
Layer | A logical group of rings, defined by a dataset and a mode (free or align ). |
Ring | A radial band, automatically computed from nodes and their expandLevels . |
Node | A declared unit of data in JSON. May have children (tree mode) or not (flat mode). |
Leaf | A node without children. |
Key-group | A logical grouping of nodes sharing the same key , used for alignment and interactions. |
Arc | A computed geometric entity ready to be rendered (x0, x1, y0, y1 ). |
Property | Type | Description |
---|---|---|
size.radius |
number |
Final radius in pixels. |
size.angle? |
number |
Total angle (default 2Ο = full circle). |
layers |
Layer[] |
List of layers from inside out. |
Property | Type | Description |
---|---|---|
id |
string |
Unique identifier. |
radialUnits |
[n,n] |
Radial interval in unit rings. |
angleMode |
"free" | "align" |
Angular partition mode. |
alignWith? |
string |
Reference layer ID (if align ). |
padAngle? |
number |
Angular spacing between arcs. |
baseOffset? |
number |
Global rotation (radians). |
arcOffsetMode? |
"relative" | "absolute" |
How offsets are applied. |
tree |
Node | Node[] |
Data for the layer. Supports tree or flat structure. |
Property | Type | Description |
---|---|---|
name |
string |
Display name. |
value |
number |
Size of the arc (summed if children exist). |
key? |
string |
Stable identifier for alignment, animation, and coloring. |
expandLevels? |
number |
Radial thickness in rings (default = 1). |
offset? |
number |
Local offset. |
color? |
string |
Custom arc color (overrides palette). |
children? |
Node[] |
Child nodes (tree mode only). |
tooltip? |
string |
Custom tooltip text. |
collapsed? |
boolean |
Keep descendants hidden from layout while their values contribute to the parent arc. |
hidden? |
boolean |
Hides the node completely. |
Property | Type | Description |
---|---|---|
layerId |
string | Origin layer ID. |
data |
Node | Reference to original node. |
x0, x1 |
number | Angular start and end (radians). |
y0, y1 |
number | Inner/outer radius (pixels). |
depth |
number | Logical depth in its layer. |
key? |
string | Copy of node key. |
percentage |
number | Relative percentage in its parent. |
npm install @akitain/sandjs
Render a sunburst in the browser:
<svg id="chart"></svg>
<script type="module">
import { renderSVG } from 'sandjs';
const config = {
size: { radius: 160 },
layers: [
{
id: 'root',
radialUnits: [0, 2],
angleMode: 'free',
tree: [
{ name: 'Data', value: 6, key: 'data' },
{
name: 'Design',
key: 'design',
value: 4,
children: [
{ name: 'UI', value: 2 },
{ name: 'Brand', value: 2 }
]
}
]
}
]
};
const chart = renderSVG({
el: '#chart',
config,
tooltip: true,
onArcClick: ({ arc }) => console.log('Pinned', arc.data.name)
});
// Update the chart later without re-attaching listeners
chart.update({
config: {
...config,
size: { radius: 180 },
}
});
</script>
The demo under demo/
shows relative/absolute offsets, tooltips, and selection callbacks. Run npm run build
and serve the folder (for example npx http-server .
) to experiment.
- Layers (
free
oralign
):free
splits siblings by value;align
reuses the angular span of a keyed arc in another layer. - Offsets:
defaultArcOffset
and per-nodeoffset
shift arcs. Inrelative
mode the offset is a fraction of the available span; inabsolute
mode it is applied in radians. - Padding: Use
padAngle
on a layer or node to reserve gap space between siblings. - Callbacks:
renderSVG
exposesonArcEnter
,onArcMove
,onArcLeave
, andonArcClick
with the arc metadata and the renderedpath
. - Tooltips: enable with
tooltip: true
or pass{ formatter, container }
for custom markup. - Breadcrumbs: pass
breadcrumbs: true
to auto-render a trail or supply{ container, formatter, separator }
;formatArcBreadcrumb(arc)
helps generate custom labels. - Highlights: enable
highlightByKey: true
(or supply options) to add a shared class for arcs with the samekey
, and optionally toggle pinned highlights viapinOnClick
. - Collapsing: set
collapsed: true
on a node to keep its descendants hidden from the rendered layout while preserving its aggregated value. - Updates: keep the returned handle from
renderSVG
and callchart.update({ config: nextConfig })
(or pass a full config) to redraw without re-binding listeners.
See src/types/index.ts
for the full TypeScript contracts.
npm run test # type check + node test runner
npm run build # rollup (ESM + minified IIFE bundles)
npm run verify # convenience: runs tests and build
dist/
contains the publishable artifacts. The IIFE bundle exposes window.SandJS
for CDN usage (https://unpkg.com/@akitain/[email protected]/dist/sandjs.iife.min.js
).
npm run verify
- Manually review the
demo/
example in a browser. - Update
CHANGELOG.md
and bump the package version. npm publish --access public
- Core layout (
layout(config)
β arcs{x0,x1,y0,y1}
) - SVG renderer (
renderSVG({ el, config })
) - JSON-driven charts (radius, layers, nodes)
- Modes
free
/align
withkey
- Basic
expandLevels
(within a layer) - Offsets:
baseOffset
,arcOffsetMode
,defaultArcOffset
- Auto color palette (category10)
- Simple interactions: hover, click callbacks
- Builds: ESM + IIFE (CDN/global)
- Publish to npm + GitHub Pages demo
- Tooltips (name, value, %)
- Breadcrumbs (full path of arc)
- Highlight by key
- Collapse/expand (
collapsed: true
) - API
update(newConfig)
(no animation yet) - Unit tests for invariants (angles, radial order)
- Animated transitions (update with interpolation by key)
- Zoom/drill-down
- Basic radial labels
- Export:
exportSVG()
,exportPNG()
- Color themes (qualitative, sequential, diverging)
- Accessibility (aria-labels, keyboard nav)
- Canvas renderer (performance for >5k arcs)
- Plugin system (legends, labels, effects)
- Layout-only mode (server / custom renderers)
- Partial angle support (gauge 180Β°/270Β°)
- Advanced animation (easing, delays)
- Large dataset tests (50k arcs in Canvas)
- Publish also on JSR (Deno/Bun)
- Online editor/playground
- Smart labels (collision detection)
- Skins/themes (flat, material, dark)
- Framework wrappers (React/Vue/Svelte)
- Full documentation site + gallery
MIT Β© Aqu1tain