diff --git a/.changeset/brown-pears-invent.md b/.changeset/brown-pears-invent.md new file mode 100644 index 000000000..08512133b --- /dev/null +++ b/.changeset/brown-pears-invent.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(Axis): Support UTC scales (`xScale={scaleUtc()}`) by filtering and formatting ticks on the same boundaries as the scale diff --git a/docs/package.json b/docs/package.json index 6bc6bb6f9..3bd555058 100644 --- a/docs/package.json +++ b/docs/package.json @@ -36,7 +36,7 @@ "@layerstack/svelte-state": "0.1.0-next.23", "@layerstack/svelte-table": "1.0.1-next.18", "@layerstack/tailwind": "2.0.0-next.21", - "@layerstack/utils": "2.0.0-next.18", + "@layerstack/utils": "2.0.0-next.19", "@napi-rs/canvas": "^0.1.97", "@sveltejs/adapter-cloudflare": "^7.2.8", "@sveltejs/kit": "^2.62.0", diff --git a/docs/src/content/components/Axis.md b/docs/src/content/components/Axis.md index 8363088c3..bac6f7c0d 100644 --- a/docs/src/content/components/Axis.md +++ b/docs/src/content/components/Axis.md @@ -17,14 +17,42 @@ Controls the number of pixels allotted for each tick (higher => fewer ticks). Wo Default: `80` for horizontal axes (top/bottom/angle) and `50` for vertical axes (left/right/radius). :: -:example{ name="linechart-tickspacing" showCode } +:example{ name="linechart-tickspacing" } -:example{ name="barchart-tickspacing" showCode } +:example{ name="barchart-tickspacing" } ::tip -See also: time scale [auto](/docs/components/Axis/time-scale-auto), [multiline](/docs/components/Axis/time-scale-auto-multiline), and [brush](/docs/components/Axis/time-scale-brush-multiline) examples +See [time scales](#time-scales) for how tick labels are chosen, and [brush](/docs/components/Axis/time-scale-brush-multiline) for tick spacing while zooming. :: +### time scales + +With no `format`, tick labels are chosen automatically from the duration between ticks — a domain spanning years is labelled with years, one spanning a minute with seconds. Resizing the chart (or changing `tickSpacing`) changes the tick density, and the labels follow. + +:example{ name="time-scale-auto" } + +Passing an explicit `format` does two things: it labels the ticks, and it **filters** them to that boundary. A `day` format keeps only ticks landing exactly on a day, so a denser tick set never repeats the same label. + +:example{ name="time-scale-auto-format-filtering" } + +::note +Because the filter is what keeps labels unique, an explicit `format` can yield fewer ticks than `tickSpacing` alone would produce. If an axis renders no ticks, check that the format's boundary matches the values — see [UTC](#utc) for the common case. +:: + +`tickMultiline` splits the automatic labels across two lines (ex. day above, month below), fitting more context into the same width. + +:example{ name="time-scale-auto-multiline" } + +#### UTC + +Ticks are filtered and labelled on the same boundaries the scale uses, so pass `xScale={scaleUtc()}` when your values are keyed on a UTC calendar date (ex. daily partitions) rather than on an instant. The default `scaleTime()` floors on _local_ boundaries, which sits one UTC offset away from each UTC day for every viewer outside UTC. + +::note +This applies to the tick _labels_ as well — a `scaleUtc()` axis formats its ticks in UTC, so a tick at UTC midnight is never labelled with the previous local day. +:: + +:example{ name="utc-scale" } + ### band scales When creating time-series bar charts, it can be useful to use a time scale axis instead of a bar scale axis. This helps show gaps in data (such as on [weekends](/docs/components/BarChart/time-scale-interval)) and provides improved axis ticks. @@ -33,7 +61,7 @@ To enable this, you must define the interval (daily, hourly, etc) of your data u Since band padding is not available when not using a band scale, you can leverage `xInset={...}` to add padding between bars. -:example{ name="barchart-xinterval-xinset" showCode } +:example{ name="barchart-xinterval-xinset" }