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.
- Import the published @askrjs/askr entrypoint.
- Keep recipes configuration next to the component, route, or server composition root that owns it.
- 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.