Pareto

Causes sorted by weight with a cumulative line (a Pareto chart). Reach for it after a bad week, to see which few causes make most of the trouble.

import { pareto } from "@umriss-ui/charts";

pareto() sorts, adds up and folds the tail into one entry that stands last whatever its size; the bars, the line and the second axis are yours to compose.

Examples

Sort causes and collect the tail

pareto() sorts descending, adds up and folds everything past collectRank into one entry that stands last; the bars and the line are yours, and the x axis reads each entry's name.

import { useMemo } from "react";
import { Legend, LimitLine, Tooltip, pareto, useChart } from "@umriss-ui/charts";

/* Why deliveries failed last month, in no particular order. */
const FAILED_DELIVERIES = [
  { name: "Damaged in transit", value: 21 },
  { name: "Nobody home", value: 312 },
  { name: "Address incomplete", value: 96 },
  { name: "Refused", value: 34 },
  { name: "Business closed", value: 58 },
  { name: "No access code", value: 147 },
  { name: "Wrong address", value: 12 },
  { name: "Parcel not found", value: 8 },
  { name: "Weather", value: 6 },
  { name: "Vehicle breakdown", value: 4 },
];

export default function ParetoExample() {
  const { entries } = useMemo(() => pareto(FAILED_DELIVERIES, { collectRank: 6, remainderName: "Other" }), []);
  const { Chart, XAxis, YAxis, Bar, Line } = useChart(entries);
  return (
    <Chart height={300} ariaLabel="Failed deliveries by cause, sorted, with the cumulative share">
      <XAxis value="name" />
      <YAxis label="Failed deliveries" />
      <YAxis
        id="share"
        position="right"
        domain={[0, 100]}
        tickFormat={(v) => `${v.toFixed(0)} %`}
        label="cumulative"
      />
      <Bar value="value" name="Failed" barWidth={0.72} />
      <Line value={(d) => d.cumulative * 100} yAxisId="share" name="cumulative" markers="always" strokeWidth={1.75} />
      <LimitLine value={80} axisId="share" severity="warning" label="80 %" inExtent={false} />
      <Legend placement="top" />
      <Tooltip mode="x" />
    </Chart>
  );
}

Keyboard

The keys of Chart apply here.

Props on this page

From ChartProps — the full table stands on Chart.

NameTypeDefaultDescription
heightnumberfills the frame, at least 300 pxHeight in CSS pixels, fixed. Left out, the chart fills its frame - a stretched grid cell, a card the grid stretches, a container of definite height - and never goes below 300 px, which is also its height in a frame without one. A different floor goes through style's minHeight (ADR-0050).
childrenReactNode—The axes, series and companions of this chart. They draw nothing themselves: each registers its configuration and the scene draws it, and the order in the JSX is the drawing order.

Accessibility

NameTypeDefaultDescription
ariaLabelstring—Required in DEV through a warning.

From XAxisProps — the full table stands on Axis.

NameTypeDefaultDescription
valuerequiredAxisField<T> | ((d: T, index: number) => AxisValue)—Where a row lies on this axis: a field of the row, compared by its name, or a function of it, compared by its source text as a series' is (ValueFunction) - with the same closure limit. A number is a position, a Date an instant, a string a category: every distinct one gets a place of its own, in the order the rows bring them, a tick and its name as the label (ADR-0052). The type decides, never the content - "2024" is a category, 2024 a number - and a row without a value has no place. The axis reads the rows of every series bound to it; where those bring their own data, name their row: <XAxis<HourCount> value="hour" />.
idstring"x"Axis id, through which series bind themselves.
labelstring—Axis title.
tickFormat(v: number) => string—Label of a tick. Compared by its source text: one that reads a changed closure variable under the same text does not relabel the axis - give it a new text or remount. A bound Intl.NumberFormat#format is compared by identity.

From YAxisProps — the full table stands on Axis.

NameTypeDefaultDescription
domain| "nice"
| "data"
| "visible"
| readonly [number, number]
"nice"As on the x axis, and "visible": what the series show inside their x axis' domain - a zoomed hour gets the hour's range, not the week's -, widened to ticks as "nice" is. Where the x domain is not fixed that is every point.
position"left" | "right""left"Which edge the axis stands at. Several y axes per side are stacked outwards, so that extents of clearly different magnitude stay readable.
idstring"y"Axis id, through which series bind themselves.
labelstring—Axis title.
tickFormat(v: number) => string—Label of a tick. Compared by its source text: one that reads a changed closure variable under the same text does not relabel the axis - give it a new text or remount. A bound Intl.NumberFormat#format is compared by identity.

From LineProps — the full table stands on Line.

NameTypeDefaultDescription
valuerequiredValue<T>—Y value - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap.
yAxisIdstring"y"Binding to a y axis.
namestring"Series n", after its place in the chartThe name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.
strokeWidthnumber1.5Line width in CSS pixels.
markers| "auto"
| "always"
| "never"
"auto"When the individual points are drawn as marks: auto every point up to 60 points and above that only a point between two gaps - it has no line to be seen by - always, or never, not even that one.

From BarProps — the full table stands on Bar.

NameTypeDefaultDescription
valuerequiredValue<T>—Height - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap.
namestring"Series n", after its place in the chartThe name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up.
barWidthnumber0.8Width as a fraction of the step; just under 1, so that neighbours do not touch. Several bar series share this fraction.

From LimitLineProps — the full table stands on LimitLine.

NameTypeDefaultDescription
valuerequirednumber | Date—Where the line lies, in domain units of its axis; along a time axis an instant, in milliseconds or as a Date.
axisIdstringthe first axis of the orientationAxis on which the value lies.
severitySeverity
"warning" | "alarm"
"alarm"Two severities, not five: five urgencies are five colours, and five colours on a dense screen are noise.
labelstring—What the value means. A line at 90 does not say what 90 is.
inExtentbooleantrueWhether the value widens the axis extent, so that the limit is certainly visible.

From LimitBandProps — the full table stands on LimitLine.

NameTypeDefaultDescription
axisIdstringthe first axis of the orientationAxis on which the value lies.
severitySeverity
"warning" | "alarm"
"warning"Two severities, not five: five urgencies are five colours, and five colours on a dense screen are noise.
labelstring—What the value means. A line at 90 does not say what 90 is.
inExtentbooleantrueWhether the value widens the axis extent, so that the limit is certainly visible.

From TooltipProps — the full table stands on Tooltip.

NameTypeDefaultDescription
mode"x" | "nearest""x""x": every series at the x position; "nearest": only the nearest point.

From LegendProps — the full table stands on Legend.

NameTypeDefaultDescription
placement"top" | "bottom""top"Which side of the plot area the legend stands on.

Every page of @umriss-ui/charts

Getting started

Chart

Series

Limits and alarms

Around the chart

API index