Skip to content

Blocks

A row is made of blocks. Each block takes values on the chart’s scale, and rhp works out where they go. You can put as many blocks in a row as you like, and any HTML around or inside them.

Bar

A bar from from to to. from is 0 if you leave it out. thick sets how thick it is: a size like "10px", or a share of the row like 0.5.

import { Chart, Plot, Bar, Label } from "@bezda/rhp";

// Opening hours: each bar runs from the opening time to the closing
// time.
export default function Hours() {
  return (
    <Chart
      scale={[6, 24]}
      ticks={[6, 9, 12, 15, 18, 21, 24]}
      format={(h) => h + ":00"}
    >
      <Plot
        shop={["Bakery", "Library", "Gym"]}
        opens={[7, 10, 6]}
        closes={[14, 19, 23]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.shop}</Label>
            <Bar from={d.opens} to={d.closes} thick="10px" />
          </div>
        )}
      </Plot>
    </Chart>
  );
}

A Bar whose to is below its from runs backward, like a negative value.

Dot

A round point at at. size sets its diameter (10px by default).

import { Chart, Plot, Dot, Label } from "@bezda/rhp";

// Race times: a dot for each runner's best lap.
export default function Laps() {
  return (
    <Chart scale={[60, 80]} format={(s) => s + " s"}>
      <Plot
        runner={["Ana", "Ben", "Chloe", "Dev"]}
        best={[71.2, 66.8, 64.5, 69.9]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.runner}</Label>
            <Dot at={d.best} size="14px" />
          </div>
        )}
      </Plot>
    </Chart>
  );
}

Tick

A short line across the row at at: a goal, a median, a threshold.

import { Chart, Plot, Bar, Tick, Label } from "@bezda/rhp";

// Steps walked against a daily goal: the bar is the steps, the tick is
// the
// goal.
export default function Steps() {
  return (
    <Chart scale={[0, 12]} format={(k) => k + "k"}>
      <Plot
        day={["Mon", "Tue", "Wed"]}
        steps={[8.2, 11.5, 5.1]}
        goal={[10, 10, 8]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.day}</Label>
            <Bar to={d.steps} />
            <Tick at={d.goal} color="ink" />
          </div>
        )}
      </Plot>
    </Chart>
  );
}

Label

Text on the chart.

  • at={value} puts it just past that value. Add side="before" to put it just before instead, which suits negative bars.
  • edge="start" puts it before the chart, where names go. edge="end" puts it after.
import { Chart, Plot, Bar, Label } from "@bezda/rhp";

// Profit and loss: the number sits just past the bar's end, on
// whichever side
// that is.
export default function Profit() {
  return (
    <Chart scale={[-40, 40]} ticks={[-40, -20, 0, 20, 40]}>
      <Plot
        month={["Jan", "Feb", "Mar", "Apr"]}
        profit={[25, -12, 8, -30]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.month}</Label>
            <Bar
              to={d.profit}
              color={d.profit < 0 ? "negative" : "positive"}
            />
            <Label
              at={d.profit}
              side={d.profit < 0 ? "before" : undefined}
            >
              {d.profit}
            </Label>
          </div>
        )}
      </Plot>
    </Chart>
  );
}

Cell

A cell that fills its spot, colored by value on the chart’s scale: from the theme’s low color to its high color. Cells make heatmaps. Here each day’s row holds a small Plot of its own, one cell per hour (more about this in charts inside rows).

import { Chart, Plot, Cell, Label } from "@bezda/rhp";

// Visitors per hour: a row per day, and a cell per hour colored by its
// count.
const visitors = [
  [2, 8, 21, 35, 30, 12],
  [4, 11, 26, 40, 34, 15],
  [9, 24, 38, 29, 18, 6],
];

export default function Visitors() {
  return (
    <Chart scale={[0, 40]} ticks={false}>
      <Plot day={["Fri", "Sat", "Sun"]} hours={visitors}>
        {(d) => (
          <div>
            <Label edge="start">{d.day}</Label>
            <Plot orientation="across" count={d.hours}>
              {(h) => (
                <div>
                  <Cell value={h.count} title={h.count + " visitors"} />
                </div>
              )}
            </Plot>
          </div>
        )}
      </Plot>
    </Chart>
  );
}

Area

A smooth shape over the scale, from a list of points, each [value, height]. The tallest point fills the row. Add mirror to draw it both ways from the middle, for violin plots.

import { Chart, Plot, Area, Label } from "@bezda/rhp";

// When people arrive at a café: a smooth shape per day, taller where
// more
// people come.
export default function Arrivals() {
  return (
    <Chart scale={[7, 19]} format={(h) => h + ":00"}>
      <Plot
        day={["Weekday", "Weekend"]}
        shape={[
          [
            [7, 1],
            [8, 6],
            [9, 4],
            [12, 7],
            [13, 5],
            [17, 3],
            [19, 1],
          ],
          [
            [7, 0],
            [9, 2],
            [11, 6],
            [13, 8],
            [15, 5],
            [17, 2],
            [19, 1],
          ],
        ]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.day}</Label>
            <Area points={d.shape} />
          </div>
        )}
      </Plot>
    </Chart>
  );
}

For a shape made from raw samples, the density helper computes the points for you.

What every block takes

Every block also takes what an HTML element takes:

  • class and style to style it,
  • color: a theme color ("series-2", "positive") or any CSS color,
  • event handlers such as onClick, and attributes such as title, data-* and aria-*,
  • children: text, an image, or any other element, drawn inside the block.

The full list of props is in the blocks reference.