@uix-design/charts
v0.3.0
Published
Charts and data visualization components for UIX Design.
Maintainers
Readme
@uix-design/charts
Public React charts package. Install with npm install @uix-design/charts.
The package does not require React UI.
Charts and data visualization package for UIX.
CSV export safety
exportChartDataToCsv(data) escapes CSV separators, quotes, CR and LF. String
values and column names beginning with formula prefixes (including leading
whitespace/control characters) are prefixed with an apostrophe and quoted;
actual numeric values remain numeric, including negative numbers. The apostrophe
may be visible to programmatic CSV consumers and preserves the literal intent.
This policy applies to the initial export: spreadsheet applications differ in
their import and re-save behavior. For workflows requiring guaranteed text-cell
types, use a typed spreadsheet format and validate it with the intended consumer.
APIs
import { Chart, LineChart } from "@uix-design/charts";
import "@uix-design/charts/styles";Use Chart for declarative ChartSpec rendering, or import the chart components directly.
The basic set covers trends (LineChart, AreaChart), categorical comparison
(BarChart, HorizontalBarChart), distributions (HistogramChart),
relationships (ScatterChart), and part-to-whole views (PieChart,
DonutChart). Every chart uses UIX color tokens and responds to its container.
const spec = {
data: [
{ month: "Jan", revenue: 1200 },
{ month: "Feb", revenue: 1800 }
],
marks: [{ type: "line" }],
encoding: {
x: { field: "month", type: "ordinal" },
y: { field: "revenue", type: "quantitative" }
},
tooltip: true
};
export function Example() {
return <Chart spec={spec} />;
}For a ranking with labels that need room to wrap, use the responsive horizontal bar component. Values remain visible as text; colors are supplementary.
import { HorizontalBarChart } from "@uix-design/charts";
<HorizontalBarChart
ariaLabel="Traffic by channel"
data={[
{ id: "organic", label: "Organic search", value: 42 },
{ id: "direct", label: "Direct", value: 31 }
]}
valueFormatter={(value) => `${value}%`}
/>;PieChart renders filled sectors; DonutChart leaves space for a center
summary. Both accept positive finite values and show a no-data state when no
valid slice remains. Use bars when readers need precise comparisons.
Status
Core charts are functional. Histogram, Sankey and network charts are first-party SVG renderers with tokenized styling, keyboard-focusable marks and tooltip support. Remaining experimental presets stay typed and documented as partial support until they receive full renderers.
Shared inspection and responsive layout
LineChart, AreaChart, BarChart, GroupedBarChart, StackedBarChart and
HistogramChart share the same Cartesian renderer. Move anywhere across the plot
or tap a category: a vertical guide and a single tooltip compare all visible
series. Tab enters the plot once; Left/Right and Home/End navigate, and Escape
closes details. Legend buttons toggle series. showDataTable exposes a semantic
HTML table including values hidden by the legend.
Categories align by label, not by array index. Labels must be unique within
one series. Missing/nonfinite observations create gaps instead of fabricated
zeroes. Use categories to supply an explicit order. Signed stacked bars maintain
separate positive and negative accumulators; filled areas and bars include zero.
Use yDomain deliberately: a custom domain can clip values outside its limits.
The container determines the rendered pixel width, preserving text and hit-target
sizes on narrow panels. width is the initial/SSR fallback; constrain the wrapper
with CSS to set a maximum width. Labels thin automatically; the data is preserved.
Line and area markers adapt to point density by default; active points remain
visible during inspection. Set showDots explicitly to override this behavior.
Axis labels account for their estimated width, including anchored endpoints.
The documentation offers 90-day, 365-day and 3,650-day fixtures with four series
(up to 14,600 observations), plus denser category, heatmap and distribution data.
These fixtures exercise interaction and layout; they are not performance guarantees.
Sankey uses horizontal scrolling when shrinking would make its nodes unreadable.
<LineChart
ariaLabel="Revenue compared with last year"
series={series}
height={300}
showCrosshair
interactiveLegend
showDataTable
minTickSpacing={72}
valueFormatter={(value) =>
new Intl.NumberFormat("en", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0
}).format(value)
}
/>Configuration
| API | Behavior |
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| series[].color, tone, strokeDasharray, strokeWidth | Explicit appearance; dash patterns distinguish comparison lines without color alone |
| ChartProvider theme={{ palette, gridColor, textColor, fontFamily }} | Scoped palette and typography; tooltip portals preserve the provider tokens |
| chartPadding, minTickSpacing, xTickFormatter, yTickCount, yDomain | Layout, axes and formatting |
| referenceLines, referenceBands | Targets and operating ranges |
| hiddenSeriesIds, defaultHiddenSeriesIds, onHiddenSeriesChange | Controlled or uncontrolled filtering |
| activeIndex, onActiveIndexChange | Coordinate guides across charts with the same category order |
| showCrosshair, showLegend, interactiveLegend, showTooltip | Enable the relevant visual/interaction features |
| renderTooltip({ datum, title, rows }) | Custom detail rendering; rows contains every visible series at the inspected category |
| tooltipPlacement, tooltipOffset, tooltipClassName | Preferred placement and presentation; overflow flips/shifts inside the visual viewport |
| showDataTable, dataTableLabel, navigationLabel, emptyLabel | Data alternative and localizable UI copy |
tooltipMode="auto" (default for every chart) and tooltipMode="floating" display
compact details near the inspected datum, flipping and shifting to fit the viewport.
They do not reserve a side panel or change the chart's dimensions. Compact overlays
let pointer hits reach the marks underneath, so moving directly to another segment
updates the details without leaving the chart. Moving over the tooltip's visible
bounds keeps it readable; Escape dismisses it.
Tooltip panels share UIX's acrylic material: a translucent theme surface with
background blur, while text and values remain opaque. Browsers without backdrop
filtering, reduced-transparency preferences and forced-colors mode use a solid
surface. Override --uix-chart-tooltip-background to tint the material and
--uix-chart-tooltip-opacity to change its fill (default: UIX strong glass, 74%).
tooltipMode="inline" explicitly reserves an in-flow detail region for applications
that need a persistent inspector. In circular charts this region sits below the plot.
tooltipPlaceholder customizes/localizes that optional region's hint.
Floating surfaces are portaled to the document body and bounded to the visual
viewport. Touch inspection persists until another selection or an outside tap.
Oversized custom panels accept pointer input for internal scrolling; prefer concise
content, a data table or an explicit inline inspector for extensive details. Override
--uix-chart-tooltip-z-index if your application's overlay layer requires it.
--uix-chart-series-1 through --uix-chart-series-8 customize categorical colors;
semantic --uix-chart-color-* overrides remain separate.
Interaction by chart type
- ComposedChart: shared category details, crosshair, series emphasis,
optional zoom/pan and image/SVG export. Use matching category order in every
series. Ctrl/Command + wheel zooms; ordinary wheel scrolling stays available.
ComboChartandDualAxisChartnow alias this working renderer. - Scatter: observation details, X/Y guides, distinct series colors/shapes and
legend emphasis.
point.sizecontrols the rendered radius, not an encoded area. - Pie/Donut: inspect amount and percentage; legends inspect the same segments.
onDatumSelectsupports drill-down. Totals stay stable during inspection. - Horizontal bars, heatmaps, ranges, sparklines, candlesticks, radar, funnel, gauge, bubble, polar, signal grids: point/cell details with the shared overlay, focus navigation, touch inspection and theme tokens. Radar compares the same axis across series; candlesticks expose Open/High/Low/Close separately.
- Sankey/Network: inspect nodes/links and emphasize connected flows. Sankey uses one value-to-width scale with separate entry/exit offsets; cyclic flows produce an explanatory state instead of a misleading Sankey.
Waterfall
WaterfallChart replaces the former placeholder. Signed deltas update the running
balance; kind: "total" displays a snapshot without adding it again. initialValue
sets the opening balance. Invalid deltas are omitted. Colors, connectors, sizing,
formatting, tooltip rendering and a data table are configurable.
<WaterfallChart
initialValue={120}
data={[
{ id: "opening", label: "Opening", kind: "total" },
{ id: "income", label: "Income", value: 85 },
{ id: "cost", label: "Costs", value: -42 },
{ id: "closing", label: "Closing", kind: "total" }
]}
showDataTable
/>Treemap and radial progress
TreemapChart (alias Treemap) replaces the former placeholder. It tiles proportional
areas, calculates parent values from children, supports drill-down/breadcrumbs and
an optional data table. Use unique IDs and finite positive leaf values. Small tiles
retain accessible names even when visible labels do not fit.
RadialBarChart compares independent values to max (or each datum's max). Rings,
legend, center content, thickness, gap, rounded ends, formatting and selection are
configurable. The detail reports values above the target while the ring is capped
at 100%. Unlike donut segments, these values do not need to add up to a whole.
Gantt migration
Gantt belongs to @uix-design/advanced. Import GanttChart and its types from
@uix-design/advanced/gantt; styles are automatic. The obsolete
@uix-design/charts/react-ui compatibility entry has been removed.
Scope and validation
This package is public. Canvas rendering, brush selections,
continuous-time scales in the component API, and the remaining placeholder presets
are not completed by these changes. ChartSpec currently renders line/area, bar and
arc marks; its broader typed schema is not a promise that every option is implemented.
Use direct components for the documented interactions above. Large data sets should
be aggregated or sampled using the existing transforms before rendering SVG.
Regression coverage includes missing-category alignment, comparison rows, keyboard navigation, filtering, portal dismissal, negative/fractional scales, mobile tooltip bounds, Waterfall totals and proportional Sankey links. The documentation pages provide interactive examples rather than separate styling implementations.
Design references: Highcharts shared tooltips, W3C hover/focus content, and Heer & Shneiderman, Interactive Dynamics for Visual Analysis.
Sales and time-based charts
FunnelChart: ordered stages, proportional widths, conversion from the previous stage, share of the first stage, loss/additions andonStepSelect. Zero denominators display unavailable ratios. Values must be finite and nonnegative; invalid entries are omitted with a visible notice. Increases stay visible.CalendarHeatmap: a responsive monthly calendar for one explicityear.datatakes{ date: "YYYY-MM-DD", value }; duplicates are summed. Missing observations remain distinct from zero, including in custom tooltips (null). All months share one intensity scale; negative values have a separate color.locale,weekStartsOn, colors, formatters and date selection are configurable. Arrow keys navigate days across month boundaries from a single tab stop.TimelineChart: grouped intervals with independent lanes for overlap. Input takes{ id, label, group, start, end }, using epoch milliseconds or ISO timestamps with an explicit timezone.domainclips the view, while tooltips and the optional data table retain exact timestamps.timeZone,locale,timeFormatter, selection and tooltips are configurable. Narrow screens scroll the axis with fixed resource labels. Use Gantt for editable task planning.
Gallery coverage
The Google Charts gallery was used as a reference for chart families, not as a rendering dependency. The calendar and timeline references informed the choice of daily activity and grouped time intervals.
| Need | Functional UIX components | | ------------------------------ | ----------------------------------------------------------------- | | Trends and comparison | LineChart, AreaChart, BarChart, HorizontalBarChart, ComposedChart | | Distribution and relationships | HistogramChart, ScatterChart, BubbleChart, RadarChart | | Composition and conversion | PieChart, DonutChart, TreemapChart, FunnelChart, WaterfallChart | | Activity and planning | HeatmapChart, CalendarHeatmap, TimelineChart | | Targets and financial ranges | GaugeChart, RadialBarChart, RangeBarChart, CandlestickChart | | Flow and relationships | SankeyChart, NetworkChart |
This is not full Google Charts parity. Geographic maps, organization charts, word trees and dedicated annotation/diff renderers are not included. Existing Sunburst, BoxPlot, ViolinPlot, OHLCChart, ChordDiagram, ParallelCoordinates, Streamgraph and RealtimeChart exports remain experimental placeholders, clearly identified as such.
ChartPresentation
ChartPresentation organizes one or more datasets into named chart views. It reuses
UIX SVG renderers and prepares/mounts only the active view. Supported types are
line, area, bar (one series), grouped-bar, stacked-bar, donut and pie
(one nonnegative series). Navigation thumbnails are fixed type glyphs, not charts
of inactive datasets. Import the component and the normal Charts stylesheet.
import { ChartPresentation, type ChartPresentationView } from "@uix-design/charts";
import "@uix-design/charts/styles";
const datasets = {
sales: {
label: "Sales",
unit: "USD",
data: [
{ month: "Jan", amount: 80 },
{ month: "Feb", amount: 95 }
]
},
target: {
label: "Target",
unit: "USD",
data: [
{ month: "Feb", amount: 100 },
{ month: "Jan", amount: 90 }
]
}
};
const series = [
{ id: "sales", dataset: "sales", x: "month", y: "amount" },
{ id: "target", dataset: "target", x: "month", y: "amount" }
];
const views: ChartPresentationView[] = [
{ id: "trend", title: "Trend", type: "line", series },
{
id: "comparison",
title: "Monthly comparison",
type: "grouped-bar",
series,
format: { locale: "en-US", currency: "USD" }
}
];
<ChartPresentation
title="Commercial report"
datasets={datasets}
views={views}
allowFullscreen
allowConfiguration
allowExport
allowAutoplay
/>;- Datasets accept readonly row arrays or
{ label?, unit?, data }. Declare units when comparing sources. Series align byxcategory, never by array index. Values must be finite numbers; null/undefined observations remain gaps. Duplicate categories require explicitaggregate: "sum" | "average" | "min" | "max" | "count". A binding may supplyfilter(row). No input records are mutated. - Views accept
description,note,categories,yLabel,showLegend,formatandmaxPoints. Cartesian views plot up to 300 categories by default, uniformly selecting shared categories including both endpoints. A visible footer reports omissions; this is a bounded overview, not extrema-preserving downsampling. Preaggregate or provide a meaningful window when every peak matters. Circular data is never sampled: aggregate categories before supplying a large composition. Use explicit series IDs andcolor/toneto keep colors stable across views. activeViewId/onActiveViewChangecontrol navigation.defaultActiveViewIdinitializes uncontrolled selection.onViewConfigurationChange(view)can persist drawer edits. Local settings reset when the consumer replaces a view descriptor.allowPresentationdefaults to true.allowFullscreen,allowConfiguration,allowExport(current SVG) andallowAutoplaydefault to false. Expanded mode retains tools; presentation mode hides tools/thumbnails while preserving view selection.onModeChangereportsembedded,expandedorpresentation. Full-window modes require Popover API support; unsupported browsers retain embedded navigation and display disabled expansion controls.- Playback starts paused, uses
autoplayInterval(default 8 seconds, minimum 5), stops at the last view and pauses on pointer entry, keyboard focus or a hidden document. It does not automatically restart. Arrow shortcuts operate outside chart inspection/input targets. Escape exits and restores focus to the trigger. labelslocalizes UI text, chart type names and record/position/omission counters.toolbaraccepts consumer-owned filters/actions and is hidden while presenting.heightcontrols the embedded plot; full-window height responds only to active layout resizing.loadinganderrorreplace the plot without mounting renderers.- The complete prepared data table is mounted only on demand and paginated in batches of 50 rows. Source record counts in the footer refer to the supplied datasets, before binding filters. Workspace controls share 32px desktop/44px touch sizing, 12px edge insets and UIX tokens; compatible Card composition adapts the outer corners through existing surface attributes. No React UI dependency is added.
Chart containers
ChartFrame and ChartFrameProps have been removed. Chart renderers remain
independent of React UI. Consumers can compose headings, actions and footers with
Card from React UI or another application-owned container.
Polar coordinates and analytical comparisons
PolarChart replaces the removed BloomChart, BloomPetal and associated props.
It uses true angle/radius coordinates rather than decorative petals. Migrate data to
series: [{ id, label, points: [{ angle, value }] }]; categorical petals cannot
infer a meaningful angle without an explicit mapping.
import { PolarChart } from "@uix-design/charts";
import "@uix-design/charts/styles";
<PolarChart
ariaLabel="Directional response"
series={[
{
id: "sensor",
label: "Sensor",
points: [
{ angle: 0, value: 90 },
{ angle: 60, value: 45 },
{ angle: 180, value: 20 },
{ angle: 300, value: 65 }
]
}
]}
type="area"
radialMax={100}
showDataTable
/>;type: line, area, scatter or bubble; each series can override it.grid: polar circles or radar polygons;angleTicksspecifies spokes.angleFormatterandvalueFormatterformat units. Angles normalize to [0, 360).radialMaxsets a fixed zero-based scale; larger values are clipped. Hiding a series preserves the domain. Invalid or negative radial values are omitted.closeddefaults to true for cyclic data.startAngledefaults to -90° (top),clockwiseto true. There is no implicit smoothing or interpolation of missing data.- For bubbles,
sizecontrols proportional area; missing or nonpositive sizes have no visible area. Points offer focus/touch details, Escape dismissal and a data table.
LineChart supports focusSeriesId (keep the selected series in its own color and soften the other colors) and
showEndLabels (direct endpoint labels with vertical collision avoidance).
For small multiples, pass the same yDomain, categories, height and tick count
to each chart. Explicit domains now also determine ticks, so panels use matching
scales regardless of their individual ranges.
See the Polar, Line and other chart-type pages for interactive advanced examples with their executable source. The polar guide follows the coordinate model in Logi Analytics. Focus and small multiples follow Government Analysis Function.
Complete component reference
The component API catalog covers every
public component value, including aliases and presets. Run pnpm check:charts-docs
to compare it with the TypeScript root exports and verify that each example is
reachable from a registered page, with executable example source displayed.
There are 36 implementations, 12 aliases/presets and 8 names without renderers.
The availability guide shows the
actual placeholder behavior; these names are not functional chart types.
ChartSpec also describes more capabilities than its current adapter implements:
use the Chart guide for its supported
fields rather than assuming every typed option affects rendering.
Character attributes: radar or polar
Use RadarChart for categorical
attributes such as strength, vitality and agility: each character is a series,
all series have the same attributes in the same order, and maxValue={100} keeps
comparisons on a fixed scale. The demo compares three fictional characters.
PolarChart
can display the same data with grid="radar", type="area", radialMax={100},
equally spaced angleTicks and category labels supplied by angleFormatter.
Its legend can hide characters and its data table exposes exact values. Normalize
incompatible units with shared, disclosed limits; do not compare polygon areas or
normalize each character independently.
Transient line focus
Set focusOnHover to emphasize the line under the pointer, its legend item, or its
endpoint label when showEndLabels is enabled. Every series starts in its normal
color. The focused series keeps that color and a stronger stroke; other lines use
pastel versions of their own colors, mixed with the current surface. Moving away
restores the palette. Keyboard focus on labels or legend items has the same effect;
Escape clears transient focus. focusSeriesId remains an optional persistent
selection underneath hover/focus. Missing observations remain gaps during hit
testing, and hidden series cannot be highlighted. This option also works when
showTooltip={false}. Legend clicks still toggle series visibility.
Polar and radar comparison focus
PolarChart and RadarChart also accept focusOnHover (off by default). Hover a
series outline, a scatter/bubble mark, or its legend name to emphasize that series
in its normal color. Other series keep their hues in softer versions. The pointer
can reach outlines underneath overlapping areas; leaving the outline or name
restores all colors. Keyboard focus on names or points has the same effect, and
Escape clears focus and details. Touch a point to focus and inspect it.
The character comparison
enables the option in both renderers with a shared 0–100 scale. Polar legend clicks
still hide/show series without changing the scale; Radar names provide focus only.
Focus works with showTooltip={false} as well.
SignalGridChart places its optional trend Sparkline below the intensity cells
in normal document flow. Both views reserve their own space, support inspection,
and respect showTooltip; no consumer positioning or corrective CSS is needed.
Focus across multi-series renderers
Use focusOnHover with LineChart, AreaChart, BarChart, ColumnChart,
GroupedBarChart, StackedBarChart, ScatterChart, ComposedChart, ComboChart
and DualAxisChart, as well as Polar and Radar. All series initially use their
normal colors. Hover a mark, a line/area outline, or its legend name to retain that
series color and soften the others in their own hues. Leaving restores the palette;
keyboard focus and touch inspection provide equivalent access. Escape clears focus.
Axes, values, positions, tooltip colors and readable text stay unchanged.
The option defaults to false in Cartesian/Polar/Radar charts. Scatter and Composed retain their existing interactive default (true). Their legend clicks still pin a series; transient hover/focus can override the pin, leaving returns to it, and Escape clears both. Cartesian legend clicks still hide/show series, and hidden series cannot be highlighted. Grouped and signed stacked bars hit-test their actual rectangles; zero-height bars do not create invisible pointer targets. Area focus uses the upper outline, so overlapping fills do not hide the comparison.
Chart forwards its focusOnHover prop to its line, area and bar adapters. In
ChartPresentation, set views[].focusOnHover for each Cartesian view. Both preserve
the same public behavior without consumer styles; controls, zoom/pan, export and
linked category inspection continue to work. The examples show their actual updated
source. Heatmap intensity, OHLC direction, circular categories and single-value
indicators do not represent multiple named series and retain their own semantics.
