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.
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>
);
}
The keys of Chart apply here.
From ChartProps — the full table stands on Chart.
| Name | Type | Default | Description |
|---|---|---|---|
height | number | fills the frame, at least 300 px | Height 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). |
children | ReactNode | — | 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. |
| Name | Type | Default | Description |
|---|---|---|---|
ariaLabel | string | — | Required in DEV through a warning. |
From XAxisProps — the full table stands on Axis.
| Name | Type | Default | Description |
|---|---|---|---|
valuerequired | AxisField<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" />. |
id | string | "x" | Axis id, through which series bind themselves. |
label | string | — | 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.
| Name | Type | Default | Description |
|---|---|---|---|
domain | | "nice" | "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. |
id | string | "y" | Axis id, through which series bind themselves. |
label | string | — | 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.
| Name | Type | Default | Description |
|---|---|---|---|
valuerequired | Value<T> | — | Y value - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap. |
yAxisId | string | "y" | Binding to a y axis. |
name | string | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
strokeWidth | number | 1.5 | Line width in CSS pixels. |
markers | | "auto" | "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.
| Name | Type | Default | Description |
|---|---|---|---|
valuerequired | Value<T> | — | Height - a number field of the row or a function of it; null/undefined/NaN/±Infinity means a gap. |
name | string | "Series n", after its place in the chart | The name in legend and tooltip. Without one a warning stands in DEV - an unnamed series is a colour nobody can look up. |
barWidth | number | 0.8 | Width 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.
| Name | Type | Default | Description |
|---|---|---|---|
valuerequired | number | Date | — | Where the line lies, in domain units of its axis; along a time axis
an instant, in milliseconds or as a Date. |
axisId | string | the first axis of the orientation | Axis on which the value lies. |
severity | Severity"warning" | "alarm" | "alarm" | Two severities, not five: five urgencies are five colours, and five colours on a dense screen are noise. |
label | string | — | What the value means. A line at 90 does not say what 90 is. |
inExtent | boolean | true | Whether the value widens the axis extent, so that the limit is certainly visible. |
From LimitBandProps — the full table stands on LimitLine.
| Name | Type | Default | Description |
|---|---|---|---|
axisId | string | the first axis of the orientation | Axis on which the value lies. |
severity | Severity"warning" | "alarm" | "warning" | Two severities, not five: five urgencies are five colours, and five colours on a dense screen are noise. |
label | string | — | What the value means. A line at 90 does not say what 90 is. |
inExtent | boolean | true | Whether the value widens the axis extent, so that the limit is certainly visible. |