Chart style

Applies to every chart.

Palette

Theme

Appearance

Depth
Surface
Background

Reading & motion

Axis
Hover
Legend
Numbers
Loading
Empty
Using chart defaults
3,109npm
1stars

Charts

Every chart, by the job it does

Trends3

  • Area
  • Line
  • Combo

Comparison4

  • Bar
  • Horizontal bar
  • Slope
  • RangeNew

Part of a whole4

  • Radial
  • Treemap
  • Funnel
  • Sankey

KPIs3

  • Stat cards
  • Progress
  • Activity ring

Patterns4

  • Heatmap
  • Scatter
  • Radar
  • Box plotNew

Cool23

  • Chord loomNew
  • Rank ribbonsNew
  • Event helixNew
  • Contour islandsNew
  • Parallel ribbonsNew
  • Sunburst terracesNew
  • Cluster constellationNew
  • Ternary prismNew
  • Wind roseNew
  • Marimekko blocksNew
  • Intersection towersNew
  • Horizon foldsNew
  • Circle archipelagoNew
  • Helix ribbonsNew
  • Voxel cloudNew
  • Arc bridgesNew
  • TerrainNew
  • Hex cityNew
  • Voxel waffleNew
  • SkylineNew
  • Block cityNew
  • RidgelineNew
  • Spiral yearNew

Finance6

  • CandlestickNew
  • IndicatorsNew
  • PriceNew
  • DepthNew
  • Order bookNew
  • PortfolioNew

Heatmap

Audience activity

11,93411,934+14.9%
Mon
Tue
Wed
Thu
Fri
Sat
Sun
00:0002:0004:0006:0008:0010:0012:0014:0016:0018:0020:0022:00
0402
Default01 / 06

Usage

Import the component and the stylesheet once. See Getting started to install the package.

import { HeatmapChartCard } from '@lilt-ui/charts';
import '@lilt-ui/charts/styles.css';
<HeatmapChartCard
  title="Audience activity"
  data={weeklyActivity}
  x="hour"
  y="day"
  value="sessions"
/>

Omit title to leave out the visible title. Set header={false} to remove the whole header, and use aria-label to name a chart inside your own card. surface="ghost" controls only the visual frame. See Card composition.

Data

Each row is one cell: x names its column, y its row, and value sets its color; TypeScript rejects anything else. Rows and columns keep the order they first appear, or pass rows and columns to set it. A cell that is null, or has no row at all, is hatched and reads “No data”, while a measured zero gets the lightest tint, so a gap never passes for a quiet hour. The headline is the sum of every known cell; aggregate switches it to a mean or max for rates.

// One row per cell: which column, which row, and its value.
const weeklyActivity = [
  { day: 'Mon', hour: '00:00', sessions: 12 },
  { day: 'Mon', hour: '02:00', sessions: 0 },
  { day: 'Mon', hour: '10:00', sessions: null }, // not recorded
  // …
];

<HeatmapChartCard
  title="Audience activity"
  data={weeklyActivity}
  x="hour"          // a text field: the column
  y="day"           // a text field: the row
  value="sessions"  // a numeric field
/>

For a working period select, pass ranges. Each range brings its own data and delta.

<HeatmapChartCard
  title="Audience activity"
  x="hour"
  y="day"
  value="sessions"
  domain={[0, 500]} // one scale for both weeks
  ranges={[
    { id: 'week', label: 'This week', data: thisWeek, delta: 0.149 },
    { id: 'last-week', label: 'Last week', data: lastWeek, delta: -0.021 },
  ]}
/>

Correlation matrix

A symmetric Pearson matrix compares each metric with every other metric. Inspection retains both rows and columns and reports the number of complete pairs. Constant values are undefined, not zero correlation. All three loading styles share the skeleton exit, entrance, pointer/keyboard pinning, touch glide, reduced motion, and accessible readings table. Aggregate marks report null as their original datum.

import { CorrelationMatrixCard } from '@lilt-ui/charts';

<CorrelationMatrixCard
  title="Campaign relationships"
  data={campaignMetrics}
  metrics={[
    { "key": "spend", "label": "Spend" },
    { "key": "visits", "label": "Visits" },
    { "key": "orders", "label": "Orders" },
    { "key": "churn", "label": "Churn" },
    { "key": "latency", "label": "Latency" },
  ]}
/>
PropTypeDescription
titlestringOptional visible title. Omit to render no title. Also supplies the accessible name unless aria-label is set.
headerbooleanDefaults to true. False removes the whole header: title, headline, delta and period controls, with no reserved space. Pass data directly when your app owns period selection.
aria-labelstringAccessible chart name, independent of the visible title. Falls back to title, then a generic chart name.
dataRow[]One row per observation. Omit when using ranges.
heightnumberMinimum plot height, default 260. Dense lanes expand to keep every mark visible.
depthbooleanLit tiles, solid bars, or spheres. Data positions remain exact; loading keeps the same depth treatment.
colorstringOverride the palette with one CSS color.
aggregate'sum' | 'mean' | 'max'Resting headline summary; Strip defaults to mean, the others to sum.
headlinenumberOverride the resting headline.
deltanumberFractional change shown alongside the headline.
deltaTone'default' | 'inverse' | 'neutral'Use inverse when a decrease is good.
rangestringStatic period label.
ranges{ id, label, data, headline?, delta? }[]Period choices with their own data.
defaultRangestringInitial period id.
localestringLocale for numbers and dates; defaults to en-US.
formatValue(value: number) => stringCustom value formatter.
badgeReactNodeContent for the glass tab above the card.
classNamestringClass on the card frame.
styleCSSProperties | ChartStyleInline styles and scoped chart variables.
onSelectionChange(selection | null) => voidReports id, original row (or null for an absent day), value, and pinned state.
renderReadout(selection | null) => ReactNodeConsumer-owned readout, including when the header is hidden.
valueFormatIntl.NumberFormatOptionsFormats the headline, tiles, and axis, e.g. currency.
surface'elevated' | 'outline' | 'ghost'Card treatment. Ghost removes the visual frame only; header and legend are independent controls.
palette'iris' | 'cobalt' | 'emerald'Series colors. Iris by default; explicit series colors still win.
numberStyle'count' | 'pop' | 'slide' | 'roll' | 'flow' | 'scramble'How the headline animates when its value changes. Count (default) counts to the new value.
loadingbooleanShows a neutral loading skeleton, not data.
loadingStyle'shimmer' | 'draw' | 'breathe'Shimmer sweeps a highlight over still shapes; draw reveals them in order; breathe lets them settle. Follows the selected look, including depth, and respects reduced motion.
empty'dots' | 'shape' | ReactElement | nullWhat the card shows when the period has no data. Dots (default) gathers a quiet dot field around the message; shape lays the chart’s own outline behind it. Pass `<ChartEmpty>` with your own words, any element of your own, or null for nothing. Both looks stay still, so empty never reads as loading, and the headline reads a dash, never zero.
motion'auto' | 'none'None turns off decorative motion; reduced motion does this automatically.
legendfalse | 'tiles' | 'inline' | 'list' | 'pills' | 'bars'Legend layout; false hides it. Correlation defaults to false.
legendSwatch'square' | 'dot' | 'line'Legend marker, square by default.
metricsCardSeries<Key>[]At least two distinct numeric metrics.
minPairsnumberMinimum complete pairs for a coefficient, default 3.
onKeyDownKeyboardEventHandler<HTMLElement>Keyboard handler on the card frame. Chart inspection also has its own keyboard handling.

Calendar heatmap

CalendarHeatmapCard lays out one UTC day per cell. Bounds default to the observed dates. Duplicate days are rejected; aggregate them first. Zero stays tinted, absent days are hatched, and unobserved days after today are outlined. Wide calendars scroll on narrow screens. All loading styles fade out through the shared skeleton lifecycle.

import { CalendarHeatmapCard } from '@lilt-ui/charts';

<CalendarHeatmapCard data={calendarActivity} date="date" value="visits" from="2026-07-01" to="2026-10-10" today="2026-09-30" />
PropTypeDescription
titlestringOptional visible title. Omit to render no title. Also supplies the accessible name unless aria-label is set.
headerbooleanDefaults to true. False removes the whole header: title, headline, delta and period controls, with no reserved space. Pass data directly when your app owns period selection.
aria-labelstringAccessible chart name, independent of the visible title. Falls back to title, then a generic chart name.
dataRow[]One row per observation. Omit when using ranges.
heightnumberMinimum plot height, default 260. Dense lanes expand to keep every mark visible.
depthbooleanLit tiles, solid bars, or spheres. Data positions remain exact; loading keeps the same depth treatment.
colorstringOverride the palette with one CSS color.
aggregate'sum' | 'mean' | 'max'Resting headline summary; Strip defaults to mean, the others to sum.
headlinenumberOverride the resting headline.
deltanumberFractional change shown alongside the headline.
deltaTone'default' | 'inverse' | 'neutral'Use inverse when a decrease is good.
rangestringStatic period label.
ranges{ id, label, data, headline?, delta? }[]Period choices with their own data.
defaultRangestringInitial period id.
localestringLocale for numbers and dates; defaults to en-US.
formatValue(value: number) => stringCustom value formatter.
badgeReactNodeContent for the glass tab above the card.
classNamestringClass on the card frame.
styleCSSProperties | ChartStyleInline styles and scoped chart variables.
onSelectionChange(selection | null) => voidReports id, original row (or null for an absent day), value, and pinned state.
renderReadout(selection | null) => ReactNodeConsumer-owned readout, including when the header is hidden.
valueFormatIntl.NumberFormatOptionsFormats the headline, tiles, and axis, e.g. currency.
surface'elevated' | 'outline' | 'ghost'Card treatment. Ghost removes the visual frame only; header and legend are independent controls.
palette'iris' | 'cobalt' | 'emerald'Series colors. Iris by default; explicit series colors still win.
numberStyle'count' | 'pop' | 'slide' | 'roll' | 'flow' | 'scramble'How the headline animates when its value changes. Count (default) counts to the new value.
loadingbooleanShows a neutral loading skeleton, not data.
loadingStyle'shimmer' | 'draw' | 'breathe'Shimmer sweeps a highlight over still shapes; draw reveals them in order; breathe lets them settle. Follows the selected look, including depth, and respects reduced motion.
empty'dots' | 'shape' | ReactElement | nullWhat the card shows when the period has no data. Dots (default) gathers a quiet dot field around the message; shape lays the chart’s own outline behind it. Pass `<ChartEmpty>` with your own words, any element of your own, or null for nothing. Both looks stay still, so empty never reads as loading, and the headline reads a dash, never zero.
motion'auto' | 'none'None turns off decorative motion; reduced motion does this automatically.
datedate, string, or numeric key of RowUTC date per cell; numbers are milliseconds since the Unix epoch.
valuenumeric key of RowCell intensity and headline value.
fromstring | number | DateInclusive UTC bounds. Defaults to first and last observed dates; at most ten years.
tostring | number | DateInclusive UTC bounds. Defaults to first and last observed dates; at most ten years.
todaystring | number | DateUTC cutoff for future cells; defaults to today.
weekStartsOn0 | 1Sunday (0) or Monday (1, default).
domain[number, number]Fixed intensity domain that must contain every value.
onKeyDownKeyboardEventHandler<HTMLElement>Keyboard handler on the card frame. Chart inspection also has its own keyboard handling.

Props

Every prop HeatmapChartCard accepts, in the order you are likely to reach for them.

PropTypeDescription
titlestringOptional visible title. Omit to render no title. Also supplies the accessible name unless aria-label is set.
headerbooleanDefaults to true. False removes the whole header: title, headline, delta and period controls, with no reserved space. Pass data directly when your app owns period selection.
aria-labelstringAccessible chart name, independent of the visible title. Falls back to title, then a generic chart name.
dataRow[]One row per cell. Omit when using ranges.
xtext key of RowPlaces each cell in a column.
ytext key of RowPlaces each cell in a row.
valuenumeric key of RowSets the color. `null`, or a cell with no row, reads “No data”.
columnsstring[]Column order. Defaults to the order columns first appear.
rowsstring[]Row order. Defaults to the order rows first appear.
domain[number, number]Values at the light and dark ends of the scale. Fix it to compare periods; defaults to zero through the highest value.
aggregate'sum' | 'mean' | 'max'How the resting headline sums up the cells. Sum by default.
heightnumberGrid height in pixels, shared by the rows. Defaults to 30 per row.
radiusnumberCell corner radius in pixels. Defaults to 5; 0 gives square cells.
gapnumberSpace between cells in pixels. Defaults to 4.
headlinenumberResting headline. Defaults to the aggregate of every known cell.
deltanumberFractional change for the chip.
deltaTone'default' | 'inverse' | 'neutral'Use inverse when a decrease is good.
rangestringStatic period label in the header.
ranges{ id, label, data, delta?, headline? }[]Turns the period label into a select. Each range swaps the cells.
colorstringAny CSS color for the dark end of the scale.
depthbooleanRaises every cell as a low tile of one height with a lit top. Color alone still carries the value.
valueFormatIntl.NumberFormatOptionsFormats the headline, tiles, and axis, e.g. currency.
surface'elevated' | 'outline' | 'ghost'Card treatment. Ghost removes the visual frame only; header and legend are independent controls.
palette'iris' | 'cobalt' | 'emerald'Series colors. Iris by default; explicit series colors still win.
numberStyle'count' | 'pop' | 'slide' | 'roll' | 'flow' | 'scramble'How the headline animates when its value changes. Count (default) counts to the new value.
loadingbooleanShows a neutral loading skeleton, not data.
loadingStyle'shimmer' | 'draw' | 'breathe'Shimmer sweeps a highlight over still shapes; draw reveals them in order; breathe lets them settle. Follows the selected look, including depth, and respects reduced motion.
empty'dots' | 'shape' | ReactElement | nullWhat the card shows when the period has no data. Dots (default) gathers a quiet dot field around the message; shape lays the chart’s own outline behind it. Pass `<ChartEmpty>` with your own words, any element of your own, or null for nothing. Both looks stay still, so empty never reads as loading, and the headline reads a dash, never zero.
motion'auto' | 'none'None turns off decorative motion; reduced motion does this automatically.
defaultRangestringInitial range id; defaults to the first supplied range.
localestringLocale used for number formatting. Defaults to en-US.
formatValue(value: number) => stringCustom value text, taking precedence over valueFormat.
badgeReactNodeContent in the tab above the card. A comparison badge can replace this while a comparison is active.
classNamestringAdditional class on the card frame.
styleCSSProperties | ChartStyleInline styles and scoped --lilt-* chart variables.