Askr
UI & Components

Recipes

Use recipes with the current published Askr packages.

  • @askrjs/askr0.0.59

How to use recipes

Create a typed plot factory once, give the root stable row data, and compose only the scales, marks, and interactions the chart needs.

  1. Import the published @askrjs/askr entrypoint.
  2. Keep recipes configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
import { createPlot } from '@askrjs/charts';

const Plot = createPlot<ProjectRow>();

<Plot.Root data={rows} rowKey={(row) => row.id} label="Revenue by day">
  <Plot.Axis axis="x" />
  <Plot.Axis axis="y" />
  <Plot.Line x="createdAt" y="revenue" />
</Plot.Root>

Time series

A typical time series pairs `Line` (or `Area`) with a `time`/`utc` scale inferred from a `Date` field, often layering a `movingAverage(field, { window })` trend line over raw `Point` markers. Set `followLatest` on `Root` when the series is live, and use actual `Date` instances in row data rather than transport strings so temporal inference and `utc` selection behave predictably.

Histogram

Bin a numeric or `Date` field with `bin(field, { thresholds })` on `Bar.x`, pair it with `count()` on `y`, and the compiler handles bucket boundaries and default axes automatically. Adding `fill` and `stack` on a categorical field turns the same histogram into a stacked breakdown by category without changing the binning logic.

Stacked bars

`Bar`'s `stack` prop takes the categorical series field directly — `stack="outcome"` — and `normalize` converts the result to percent stacks. For cases where the numeric channel itself needs composing first, the `stack(input, options?)` and `normalize(input)` expression helpers do the same accumulation with explicit `offset` (`zero`, `diverging`, `expand`) and `order` control.

Dashboard polling

For a plot driven by periodic fetches, pass `data` as a reactive `() => readonly Row[]` getter and update the underlying array with `appendPlotRows` or `upsertPlotRows` on each poll, trimming with `trimPlotRows` so the series doesn't grow forever. Combine that with `followLatest` and `PlotApi.resumeLive()` so a viewer who's paused to inspect a spike doesn't get pulled back to the live edge by the next poll.