Sorting and motion
Sorting
order sets where each row sits.
The easiest way is sortBy:
<Plot … order={sortBy("votes", "desc")}> // largest first
<Plot … order={sortBy("votes")}> // smallest first
<Plot … order={sortBy((d) => d.name)}> // by any value
Rows with equal values keep their places, so ties don’t flicker.
order can also be a list of positions, one per row: [2, 0, 1] puts the first row third.
A position of null hides that row.
import { createSignal } from "solid-js";
import { Chart, Plot, Bar, Label, sortBy } from "@bezda/rhp";
export default function Votes() {
const [votes, setVotes] = createSignal([34, 21, 45, 12, 28]);
const [js, setJs] = createSignal(false);
const [order, setOrder] = createSignal("desc");
const vote = () =>
setVotes(
votes().map((v) =>
Math.max(0, v + Math.round(Math.random() * 20 - 10)),
),
);
return (
<>
<div class="demo-controls">
<button onClick={vote}>New votes</button>
<button
onClick={() => setOrder(order() === "desc" ? "asc" : "desc")}
>
Sort {order() === "desc" ? "up" : "down"}
</button>
<label>
<input
type="checkbox"
checked={js()}
onChange={(e) => setJs(e.target.checked)}
/>{" "}
JS version
</label>
</div>
<Chart scale={[0, 60]} animate={js()}>
<Plot
name={["Maya", "Leo", "Ivy", "Omar", "Zoe"]}
votes={votes()}
order={sortBy("votes", order())}
>
{(d) => (
<div>
<Label edge="start">{d.name}</Label>
<Bar to={d.votes} />
<Label at={d.votes}>{Math.round(d.votes)}</Label>
</div>
)}
</Plot>
</Chart>
</>
);
}How things move
When a value changes, its bar grows or shrinks, and when the order changes, rows slide to their new places. rhp has two ways to do this.
The CSS version is the default. The browser animates each change with CSS transitions: 0.15 s for values, 0.3 s for rows sliding. It costs almost nothing, even with many charts.
The JS version moves the numbers themselves, frame by frame, on one clock for the whole page.
Turn it on with animate on the Chart or a Plot.
Everything drawn from a value moves together with it, so a label rides exactly on its bar’s end, and two rows cross exactly when their values are equal.
<Chart animate>…</Chart> // the JS version
<Chart animate={{ duration: 400, ease: "ease-in-out" }}>…</Chart> // with your own timing
<Plot animate={["votes"]}>…</Plot> // only some values move
Try both with the checkbox above.
Timing
In the CSS version, set the timing in a row’s CSS:
.row { --rhp-length-time: .4s; --rhp-length-ease: ease-in-out; --rhp-slide-time: .5s; }
To time a whole chart at once, set the same variables on the Chart:
<Chart style={{ "--rhp-length-time": ".4s", "--rhp-slide-time": ".5s" }}>…</Chart>
In the JS version, pass duration (ms), ease and slide (ms) to animate:
<Chart animate={{ duration: 400, ease: "ease-in-out", slide: 200 }}>…</Chart>
Any time works, and 0 turns motion off: --rhp-length-time: 0s in the CSS version, or duration: 0 in the JS version, and values jump straight to where they’re going.
Reduced motion
If someone has asked their system for less motion, rhp jumps to new values instead of animating them.
Other ways to reorder
reorder on a Plot picks how rows change places:
"slide"(the default): rows slide on screen."move": rows jump, and their elements move in the page, so the page’s reading order follows the sort."refill": rows stay put and swap contents.