Histogram
import { Histogram } from '@absoluteui/components/histogram';import '@absoluteui/components/histogram/style.css';Using Angular? See Histogram for Angular.
What it does
Section titled “What it does”An accessible SVG histogram of the distribution of raw numeric values in adjacent bins on a linear x axis. It provides:
- automatic bins (Sturges’ rule on nice boundaries), a bin count, or explicit thresholds; bins are lower-inclusive and the last bin is also upper-inclusive;
- the binning as a reusable module function,
computeBins, which also reports missing and out-of-range values; - keyboard-reachable bins (one tab stop), including empty bins, with a tooltip on focus and hover (“10 to 20: 14 values”);
- a count axis that prints integer ticks only;
- a generated accessible summary (value count, bin count, binned range, most frequent bin, values outside the bins) and a data table fallback (bin, count).
When to use
Section titled “When to use”- The shape of a distribution of one numeric variable (response times, amounts, scores).
- Checking skew, spread, and outliers before choosing a summary statistic.
When not to use
Section titled “When not to use”- Comparing categories: use Bar Chart.
- Comparing distributions of several groups: use Box Plot.
- Relationships between two variables: use Scatter Chart.
Examples
Section titled “Examples”Response-time distribution with automatic bins
Section titled “Response-time distribution with automatic bins”import { Histogram } from '@absoluteui/components/histogram';
const values = Array.from({ length: 500 }, (_, i) => 80 + ((i * 37) % 200));const host = document.createElement('div');document.body.append(host);const chart = Histogram.create(host, { label: 'Response times', values, binFormat: { style: 'unit', unit: 'millisecond' }, xAxis: { label: 'Response time' },});host.dataset.bins = String(chart.bins.length);Explicit thresholds and computeBins for a custom table
Section titled “Explicit thresholds and computeBins for a custom table”import { Histogram, computeBins } from '@absoluteui/components/histogram';
const scores = [12, 45, 67, 68, 71, 88, 90, 95, null, 102];const thresholds = [0, 50, 70, 90, 100];const { bins, outside, missing } = computeBins(scores, { bins: thresholds });const host = document.querySelector<HTMLElement>('#scores');if (host) { Histogram.create(host, { label: 'Exam scores', values: scores, bins: thresholds, color: 3, dataTable: 'visible' }); host.dataset.counts = bins.map((b) => String(b.count)).join(','); host.dataset.outside = String(outside + missing);}import { Histogram } from '@absoluteui/components/histogram';import '@absoluteui/components/histogram/style.css';
const host = document.querySelector<HTMLElement>('#amounts');if (host) { const chart = Histogram.create(host, { label: 'Order amounts', values: [12, 18, 25, 31, 40, 44, 52, 67, 89, 120], bins: 5, min: 0, max: 150, binFormat: { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }, xAxis: { label: 'Amount' }, }); chart.update({ values: [15, 22, 30, 48, 75] });}More usage
Section titled “More usage”import { Histogram, computeBins } from '@absoluteui/components/histogram';
const values = [120, 135, 160, 180, 210, 240, 250, 310, null];const host = document.createElement('div');document.body.append(host);const chart = Histogram.create(host, { label: 'Response times', values, binFormat: { style: 'unit', unit: 'millisecond' } });
// The same binning for a custom table or export.const { bins, outside, missing } = computeBins(values, { bins: [100, 200, 300] });host.dataset.info = `${String(chart.bins.length)} bins; ${String(bins.length)} custom; ${String(outside)} outside; ${String(missing)} missing`;Export: @absoluteui/components/chart-export (chartToSvg, chartToPng, downloadChart) exports any chart instance to SVG or PNG.
Anatomy
Section titled “Anatomy”<div class="aui-chart aui-histogram [aui-chart--patterns]"> <div class="aui-chart__header"> <div class="aui-chart__title" id="T">title</div> <p class="aui-chart__description" id="D">description</p> <div class="aui-chart__toolbar" hidden/> </div> <ul class="aui-chart__legend" aria-label="Legend" hidden/> (always empty) <div class="aui-chart__body"> (height: --aui-chart-height) <svg class="aui-chart__svg" role="group" aria-roledescription="histogram" aria-labelledby="T" aria-describedby="D S"> <g class="aui-chart__grid" aria-hidden="true"/> <g class="aui-chart__axis …" aria-hidden="true"/> <g class="aui-histogram__bars aui-chart__series--c1"> <rect class="aui-chart__mark aui-chart__bar" role="img" aria-label="0 to 10: 14 values" tabindex="0"/> <rect class="aui-chart__mark aui-chart__bar" role="img" aria-label="10 to 20: 0 values"/> </g> </svg> <div class="aui-chart__empty" hidden/> <div class="aui-chart__tooltip" aria-hidden="true" hidden/> </div> <p class="aui-chart__summary" id="S" hidden>generated summary</p> <div class="aui-chart__data">...Show data table...</div></div>API reference
Section titled “API reference”Factory
Section titled “Factory”Histogram.create(host: HTMLElement, options: HistogramOptions): HistogramGlobal configuration key: histogram (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Chart title: visible text and the accessible name of the plot (aria-labelledby). Required. | |
hideLabel |
boolean |
false |
Visually hide the title; it stays the accessible name. |
description |
string |
Visible description below the title, also referenced by aria-describedby (text only). | |
summary |
string |
Replaces the generated accessible summary (aria-describedby). | |
valueFormat |
Intl.NumberFormatOptions |
Number format of bin boundaries (x axis ticks, bar labels, tooltips, table, summary) when binFormat is not set. Counts always use the plain locale number format. | |
formatValue |
(value: number) => string |
Custom text for bin boundaries (x axis ticks included) when binFormat is not set. Counts are not affected. | |
hiddenSeries |
readonly string[] |
Accepted and validated (string[]) for the shared chart contract; a histogram has one data set, so it has no effect. | |
values |
readonly (number | null)[] |
Raw values to bin; null, NaN, and infinities are ignored (counted as missing). Required. | |
bins |
'auto' | number | readonly number[] |
"auto" |
auto: Sturges’ rule on nice boundaries; a number (integer 1-500): about that many bins on nice boundaries; an array: 2-501 ascending thresholds (bin edges). |
min |
number |
Lower edge of the binned domain (finite); with auto or count bins it becomes the exact first edge. Default: a nice boundary at or below the data minimum. Ignored for binning when bins is an array of thresholds (still validated). Values outside the bins are counted and named in the summary. | |
max |
number |
Upper edge of the binned domain (finite, greater than min); with auto or count bins it becomes the exact last edge. Default: a nice boundary at or above the data maximum. Ignored for binning when bins is an array of thresholds. | |
color |
ChartColor |
1 |
Palette slot 1-8 of the bars. |
binFormat |
Intl.NumberFormatOptions |
Number format of bin boundaries (axis, labels, tooltips, table, summary). Default: formatValue, else valueFormat. | |
xAxis |
{ label?: string } |
X axis title (also the first table column header; default “Bin”). | |
yAxis |
{ label?: string; min?: number; max?: number; tickCount?: number; includeZero?: boolean } |
Count axis: title (default “Count”, always drawn), fixed domain (bars taller than max are clipped), and tick count (2-20). Only integer ticks are printed. includeZero is accepted but has no effect (the count axis starts at zero unless min is set). | |
legend |
'auto' | 'show' | 'hide' |
"auto" |
Accepted for the shared configuration; a histogram never shows a legend (the legend list stays empty and hidden). Globally configurable. |
dataTable |
'toggle' | 'visible' | 'hidden' | 'none' |
"toggle" |
Data table fallback with the exact data: behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable. |
tooltip |
boolean |
true |
Tooltip on pointer hover and keyboard focus. Globally configurable. |
patterns |
boolean |
false |
Toggles the aui-chart–patterns host class; the single bar series draws no texture. Globally configurable. |
height |
number |
300 |
Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable. |
locale |
string |
"en-US" |
Number and message locale. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
rtl mirrors the x axis (lowest bin at the right), puts the count axis on the right, and swaps ArrowLeft/ArrowRight. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
The host element. |
element |
SVGSVGElement |
The plot (svg role=“group”), named by the title and described by the summary. |
summary |
string |
The generated (or custom) accessible summary. |
bins |
readonly HistogramBin[] |
Bins of the current data: { from, to, count }; lower-inclusive, the last bin also upper-inclusive. |
hiddenSeries |
string[] |
Always empty. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
update(options: Partial<HistogramOptions>): void |
Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same mark when it still exists. |
setSeriesVisible(id: string, visible: boolean): void |
Inherited from the shared chart controller; no visible effect. |
destroy(): void |
Remove rendering, host classes, listeners, the resize observer, and the configuration subscription. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-chart |
Host (shared chart chrome). |
aui-histogram |
Host modifier for this chart type. |
aui-chart--patterns |
patterns option on: textures (and dash patterns) shown. |
aui-chart__header / __title / __title--hidden / __description |
Title and description. |
aui-chart__legend / __legend-entry / __legend-item / __legend-item--hidden / __legend-label |
Legend list (always empty and hidden for a histogram). |
aui-chart__swatch |
aria-hidden legend and tooltip key (marker, dash, texture). |
aui-chart__body / __svg / __layer |
Plot container (height from –aui-chart-height), SVG, and drawing layer. |
aui-chart__grid / __gridline / __zero-line / __axis / __axis-line / __tick-label / __axis-title |
Axes (aria-hidden). |
aui-chart__series--c1 ... --c8 |
Palette slot classes; set –aui-chart-color from color-chart-<n>. |
aui-chart__mark / __mark--active / __mark--hover |
Focusable data mark and its states. |
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value |
Tooltip (aria-hidden; the focused mark carries the same text). |
aui-chart__empty |
Empty state text (No data, All series are hidden). |
aui-chart__summary |
Hidden summary referenced by aria-describedby. |
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric |
Data table fallback. |
aui-chart__bar / __line / __area / __point / __connector / __value-label |
Shared mark styles (chart-marks): bars, lines, areas, point markers, dashed connectors, printed values. |
aui-histogram__bars |
Bars group (carries the aui-chart__series–c<n> slot class). |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”interface HistogramBin { readonly from: number; readonly to: number; readonly count: number }interface HistogramBinning { bins?: 'auto' | number | readonly number[]; min?: number; max?: number }type HistogramConfig = ChartBaseConfig; // { legend; dataTable; tooltip; patterns; height }interface HistogramOptions extends ChartCommonOptions, Partial<HistogramConfig>, HistogramBinning { values: readonly (number | null)[]; color?: ChartColor; binFormat?: Intl.NumberFormatOptions; xAxis?: { label?: string }; yAxis?: HistogramValueAxis; // { label?; min?; max?; tickCount?; includeZero? }}function computeBins(values: readonly (number | null)[], binning?: HistogramBinning): { bins: HistogramBin[]; outside: number; missing: number };Accessibility
Section titled “Accessibility”Pattern: SVG chart as a named, described group (role=“group” with aria-roledescription) of role=“img” data marks with roving focus; data table fallback (native table). Follows the WAI Complex Images tutorial (short name plus long description) and the roving tabindex technique of WAI-ARIA APG.
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| ArrowLeft / ArrowRight (also ArrowUp / ArrowDown) | Bin focused | Previous / next bin; Left/Right are mirrored in RTL. Empty bins are reachable too. |
| Home / End | Bin focused | First / last bin. |
| PageUp / PageDown | Bin focused | Ten bins back / forward. |
| Escape | Tooltip visible | Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move. |
| Tab / Shift+Tab | Any | One tab stop for the plot (the active bin), then the Show data table button and table region. |
| Element | Role |
|---|---|
| svg.aui-chart__svg | group with aria-roledescription (localized chart type), named by the title |
| data marks | img with an aria-label: bin range and value count |
| axes, tooltip | aria-hidden (decorative duplicates of the accessible data) |
| data table | table (native) with caption, column headers, and row headers; wide tables scroll in a focusable region |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-labelledby |
svg | id of the visible (or visually hidden) title |
aria-describedby |
svg | description id (when provided) and the generated summary id |
aria-roledescription |
svg | Localized “histogram” |
aria-label |
each mark | Localized “{from} to {to}: {count} values” (pluralized) |
tabindex |
active mark | 0 on exactly one mark (roving); other marks have none |
aria-expanded / aria-controls |
Show data table button | Table open state and the table region id |
Roving focus: one bin is in the tab sequence and remembers the last visited bin across re-renders (resize, update). Toggling the table keeps focus on the table button.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The generated summary names the value count, bin count, the binned range, the most frequent bin, and values outside the bins.
- One data set, so no color coding is needed; bars are separated by a surface-colored outline.
- Forced colors: bars use CanvasText with a Canvas outline (hovered and active bar outlined in Highlight); gridlines GrayText, axes and text CanvasText; focus uses Highlight.
- No animation: nothing moves on render; hover and focus emphasis transitions are removed under prefers-reduced-motion and animation: none.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
- aria-roledescription support varies; screen readers without it announce “group”.
Behavior
Section titled “Behavior”States
Section titled “States”default, empty (“No data”), bin focused (tooltip), hovered, table open.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| plot not focused | Tab | active bin focused, tooltip shown |
| bin focused | arrow keys, Home, End, PageUp, PageDown | another bin focused |
| tooltip visible | Escape | tooltip hidden, focus unchanged |
| table closed | Show data table | table built and shown |
| any | update({ values }) |
bins recomputed and re-rendered; focus kept on the same bin index |
| any | container resize | re-render at the new width; focus kept on the same bin |
Accessibility notes
Section titled “Accessibility notes”- The summary names the type, value count, bin count, the binned range, the most frequent bin, and values outside the bins, for example “histogram, 8 values in 4 bins, from 0 sec to 8 sec. Most values: 2 sec to 4 sec (5 values).” Values outside the bins add “3 values outside the bins.”
- One data set, so no color coding is needed; adjacent bars are separated by a surface-colored outline.
- Forced colors: bars use
CanvasTextwith aCanvasoutline; the hovered and active bar and focus useHighlight. Nothing animates. - Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
Responsive behavior
Section titled “Responsive behavior”The width follows the container (ResizeObserver); the height is height. Bin edge labels are thinned (every k-th edge) so they never crowd. Reflows at 320 CSS px.
Right-to-left
Section titled “Right-to-left”direction: 'rtl' mirrors the x axis (lowest bin at the right), puts the count axis on the right, and swaps ArrowLeft/ArrowRight.
Theming
Section titled “Theming”The bar color comes from color-chart-<n> via color (slot 1 by default). Gridlines use color-chart-grid, axes color-chart-axis, the hovered or active bar outline color-text.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { histogram: { dataTable: 'visible', height: 260 } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
Timezones
Section titled “Timezones”Not applicable: numeric axes only; no dates are formatted.
None. No legend or toolbar is shown.
Security
Section titled “Security”All text uses textContent; SVG is built with createElementNS. Colors are classes; sizes and the tooltip position are written through the CSSOM. No innerHTML, style attributes, or inline handlers.
Data handling
Section titled “Data handling”Renders the given data only; no persistence, network access, or telemetry. Values are not logged; validation errors name the option, never its value.
Performance
Section titled “Performance”Budget: Histogram 10,000 values create < 40 ms in headless Chromium (e2e performance test), including binning and the first render (tests/e2e/perf-r3.spec.ts). Binning is one pass for the extent plus a binary search per value; the DOM has one node per bin; the data table is built only when opened in toggle mode.
Supported data scale
Section titled “Supported data scale”Tested with 10,000 values. Up to 500 bins (count) or 501 thresholds; the value count is not capped, and DOM size depends on the bin count only.
Edge cases
Section titled “Edge cases”- No values, or only missing values: “No data”.
- A value equal to an inner edge falls in the upper bin; a value equal to the last edge falls in the last bin (for example thresholds
[0, 10, 20]: 10 counts in 10-20, 20 counts in 10-20). - Values outside
min/maxor the thresholds are counted inoutside, named in the summary, and included in the summary’s value count; they are in no bin. - Missing values (
null,NaN, infinities) are excluded from all counts exceptmissing. - All values equal: the domain is padded around the value (10% each side, or 0-1 for zero).
- Empty bins are zero-height bars that stay focusable.
- Counts above a fixed
yAxis.maxare clipped at the top of the plot. formatValueapplies to bin boundaries unlessbinFormatis set; counts are never custom-formatted.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
HISTOGRAM_OPTIONS |
configuration | Missing label; values not an array of numbers or null; bins not 'auto', an integer 1-500, or 2-501 strictly ascending finite thresholds; non-finite min/max; max not greater than min; color outside 1-8; invalid binFormat, xAxis, or yAxis. |
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION |
configuration | Invalid or unknown configuration. |
A failed construction leaves the host untouched; a failed update() keeps the previous state. computeBins does not validate.
Known limitations
Section titled “Known limitations”- One data set per chart (no overlaid distributions).
- Bins are lower-inclusive; the last bin is also upper-inclusive.
- A bin count is approximate (nice boundaries), unless
minandmaxfix the outer edges. - Only integer count ticks are printed.
- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Density curves, cumulative histograms, and logarithmic axes.
- Weighted values.
- Zoom, pan, and crosshair.
- HTML in labels or tooltips.