Skip to content

Your first chart

We’ll draw how much fruit a shop sold today, in four steps.

1. Bars

A Chart sets the scale: here, from 0 to 30. A Plot inside it gets the data. Its child is the row, written as a function of d, the row’s data.

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

export default function FirstChart() {
  return (
    <Chart scale={[0, 30]}>
      <Plot sold={[12, 18, 7, 22]}>
        {(d) => (
          <div>
            <Bar to={d.sold} />
          </div>
        )}
      </Plot>
    </Chart>
  );
}

sold is a list, so the Plot makes one row per number. In each row, d.sold is that row’s number, and the Bar runs from 0 to it.

A row is always one element that holds everything drawn in it: here, a <div> around the Bar. rhp stacks that element with the others and moves it when the rows are sorted, and the blocks inside it are placed by their values.

2. Names and numbers

Give the Plot a second list, fruit, and each row gets its item as d.fruit. A Label with edge="start" sits at the start of the chart, and one with at sits just past a value.

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

export default function FirstChart() {
  return (
    <Chart scale={[0, 30]}>
      <Plot
        fruit={["Apples", "Bananas", "Cherries", "Kiwis"]}
        sold={[12, 18, 7, 22]}
      >
        {(d) => (
          <div>
            <Label edge="start">{d.fruit}</Label>
            <Bar to={d.sold} />
            <Label at={d.sold}>{d.sold}</Label>
          </div>
        )}
      </Plot>
    </Chart>
  );
}

3. Data that changes

Keep the numbers in a signal, Solid’s box for a value that changes. When you set it, the chart updates: the bars grow or shrink.

order sorts the rows. sortBy("sold", "desc") puts the largest first, and the rows slide to their new places.

import { createSignal } from "solid-js";
import { Chart, Plot, Bar, Label, sortBy } from "@bezda/rhp";

export default function FirstChart() {
  const [sold, setSold] = createSignal([12, 18, 7, 22]);
  const newNumbers = () =>
    setSold(sold().map(() => Math.round(Math.random() * 30)));
  return (
    <>
      <div class="demo-controls">
        <button onClick={newNumbers}>New numbers</button>
      </div>
      <Chart scale={[0, 30]}>
        <Plot
          fruit={["Apples", "Bananas", "Cherries", "Kiwis"]}
          sold={sold()}
          order={sortBy("sold", "desc")}
        >
          {(d) => (
            <div>
              <Label edge="start">{d.fruit}</Label>
              <Bar to={d.sold} />
              <Label at={d.sold}>{d.sold}</Label>
            </div>
          )}
        </Plot>
      </Chart>
    </>
  );
}

Nothing else is needed: no update calls, no redraws. The chart reads the signal, so it knows when the numbers change.

4. Style

slat() gives the row its own look. Its css is plain CSS for the classes in the row, and it only reaches this chart’s rows. thickness sets each row’s height, and series() gives each row a color from the theme.

import { createSignal } from "solid-js";
import {
  Chart,
  Plot,
  Bar,
  Label,
  slat,
  sortBy,
  series,
} from "@bezda/rhp";

const Row = slat(
  {
    thickness: 40,
    css: `
      .row:hover {
        background: color-mix(in srgb, var(--rhp-ink) 8%, transparent);
        border-radius: 8px;
      }
      .bar { --rhp-end-radius: 8px; }
      .value { font-weight: 700; color: var(--rhp-color); }
    `,
  },
  (d) => (
    <div class="row">
      <Label edge="start">{d.fruit}</Label>
      <Bar to={d.sold} color={d.color} class="bar" />
      <Label at={d.sold} class="value">
        {d.sold}
      </Label>
    </div>
  ),
);

export default function FirstChart() {
  const [sold, setSold] = createSignal([12, 18, 7, 22]);
  const newNumbers = () =>
    setSold(sold().map(() => Math.round(Math.random() * 30)));
  return (
    <>
      <div class="demo-controls">
        <button onClick={newNumbers}>New numbers</button>
      </div>
      <Chart scale={[0, 30]}>
        <Plot
          fruit={["Apples", "Bananas", "Cherries", "Kiwis"]}
          sold={sold()}
          color={series()}
          order={sortBy("sold", "desc")}
        >
          {Row}
        </Plot>
      </Chart>
    </>
  );
}

A few things to notice in the CSS:

  • .row:hover lights up the row under the pointer.
  • --rhp-end-radius rounds the bar’s end only. rhp reads a few variables like this one; they’re listed in Styling.
  • var(--rhp-color) is the bar’s color, so the number matches its bar.

Where to go next

  • Data: lists, row objects, computed values and keys.
  • Blocks: dots, ticks, labels, cells and shapes.
  • Styling: everything about making charts look the way you want.
  • The gallery: twenty charts, each with its code, to copy from.