Built-in charting: date axis

Group by a real date column and the built-in Chart panel adds a Date axis toggle - proportional time gaps + real date ticks - alongside Log scale. A daily-signups sheet you can retype, re-pick, or filter live.

A live, editable Svelte 5 data grid example from the SvGrid gallery (Charts). See the SvGrid documentation for the full API.

About this example

A date axis in the built-in chart panel of the Svelte 5 data grid. Group a daily signups sheet by its date column and the panel adds a Date axis toggle that spaces points by actual time with real date ticks, alongside a Log scale toggle for the wide-range value axis; both are one click, live, and persist in saved views. Retype a value, re-pick a column or filter the grid and the line re-plots.

A daily signups sheet with a real date column. Because the group-by column is a date, the chart panel offers a **Date axis** toggle (space points by actual time, real date ticks) on top of the usual pickers - and a **Log scale** toggle for the wide-range value axis. Both are one-click, live, and persist in saved views. Filter or sort the grid and the line re-plots.

Imports, features and API used

Imports: @svgrid/grid

Columns: date (Date), channel (Channel), device (Device), signups (Signups), revenue (Revenue)

Frequently asked questions

When does the Date axis toggle appear?

When the Group by column has cellDataType date. The panel then offers proportional time spacing instead of equal steps.

What does Log scale help with?

Values that span orders of magnitude, such as signups from a few dozen to thousands; a base-10 axis keeps the small days visible next to the large ones.

Are the toggles saved?

Yes. They are part of the chart state that saved views capture, so a view restores the same axis settings.

Related documentation

Related articles

  • Sparkline Cells in a Svelte Data Grid - Show inline trend sparklines inside grid cells using SvGrid's built-in sparkline column property - no charting library needed, just a field that holds a number array.
  • Immutable Grid Updates Without Killing Performance - Surgical immutability - how to get predictable reactivity in SvGrid without the cost of cloning everything on every change.
  • Immutable Data Updates in Svelte 5 - Svelte 5 runes track both mutation and reassignment, but for grids and lists, the way you update data determines whether re-renders are surgical or wasteful. Here are the patterns that actually hold up.

Source code (358-charting-by-date.svelte)

<script lang="ts">
  /**
   * 358. Charting by date (time axis + log scale)
   * ---------------------------------------------
   * A daily signups sheet with a real date column. Because the group-by column
   * is a date, the chart panel offers a **Date axis** toggle (space points by
   * actual time, real date ticks) on top of the usual pickers - and a **Log
   * scale** toggle for the wide-range value axis. Both are one-click, live, and
   * persist in saved views. Filter or sort the grid and the line re-plots.
   */
  import { SvGrid, tableFeatures, type GridColumns } from '@svgrid/grid'

  type Row = { date: string; channel: string; device: string; signups: number; revenue: number }

  // 45 days x 3 channels x 2 devices, with a growth trend + weekly wobble + a spike.
  const CHANNELS = ['Organic', 'Paid', 'Referral']
  const DEVICES = ['Desktop', 'Mobile']
  const base: Record<string, number> = { Organic: 120, Paid: 80, Referral: 40 }
  const rows0: Row[] = []
  for (let d = 0; d < 45; d++) {
    const date = new Date(Date.UTC(2026, 0, 1 + d)).toISOString().slice(0, 10)
    const weekend = (d % 7 === 5 || d % 7 === 6) ? 0.7 : 1
    const spike = d === 30 ? 4 : 1 // launch-day spike -> log scale earns its keep
    for (const channel of CHANNELS) {
      for (const device of DEVICES) {
        const trend = 1 + d * 0.05
        const signups = Math.round(base[channel]! * trend * weekend * spike * (device === 'Mobile' ? 0.6 : 1))
        rows0.push({ date, channel, device, signups, revenue: signups * 12 })
      }
    }
  }

  let rows = $state<Row[]>(rows0)
  const features = tableFeatures({})

  const columns: GridColumns<Row> = [
    { field: 'date', header: 'Date', width: 120, cellDataType: 'date' },
    { field: 'channel', header: 'Channel', width: 120 },
    { field: 'device', header: 'Device', width: 110 },
    { field: 'signups', header: 'Signups', width: 110, align: 'right', cellDataType: 'number', format: { type: 'number', options: { maximumFractionDigits: 0 } } },
    { field: 'revenue', header: 'Revenue', width: 130, align: 'right', cellDataType: 'number', format: { type: 'currency', currency: 'USD', options: { maximumFractionDigits: 0 } } },
  ]
</script>

<div class="demo-page" style="height: 620px; display: flex; flex-direction: column;">
  <p class="demo-lede">
    A daily signups sheet charted <strong>by date</strong>. The group-by column is a real date, so the
    <strong>Chart</strong> panel adds a <strong>Date axis</strong> toggle (proportional time gaps + date ticks)
    next to <strong>Log scale</strong>. Toggle either live, change the pickers, or filter the grid.
  </p>
  <div style="flex: 1; min-height: 0;">
    <SvGrid
      columnResize
      data={rows}
      columns={columns}
      features={features}
      selectionMode="cell"
      containerHeight="100%"
      charting={{
        defaultOpen: true,
        width: 520,
        defaultType: 'line',
        dimension: 'date',
        series: 'channel',
        measures: 'signups',
        timeAxis: true,
      }}
    />
  </div>
</div>

View this example on GitHub

More Charts examples

  • Chart a selection (context menu) - With integrated charting enabled, the right-click menu gains a Chart selected range item: select a block of cells, right-click, and the chart panel opens scoped to that range - the Excel chart-this gesture, built in. The item appears only when charting is on and is appended to the default context menu automatically.
  • Chart view of the grid - The `chart` prop turns the same <SvGrid> into a chart, driven by the grid’s filtered + sorted rows (search + sort flow through). A view of the grid like board and scheduler, but the renderer is free: the grid lazy-loads a built-in view wrapping the standalone SvChart via rowsToChartSpec. Flip Table <-> Chart (bar / line / area) over one source of truth.
  • Candlestick / OHLC - Candlestick and OHLC price marks with an ordinal date axis. ChartSeries.ohlc carries the four prices while values keeps the closes, so the CSV export, the screen-reader table and a 10-day moving average all work with no candle-specific code. Toggle the axis: a real time axis opens a gap over every weekend, an ordinal one spaces sessions evenly and still labels them by date. The strip under the plot is the chart brush: drag its window to pan, drag an edge to resize.
  • Box plot + error bars - Distribution rather than average: box plots with the 1.5 IQR whisker rule and individual outliers, next to the same data as a bar chart of the means with error bars. two regions with nearly identical means sit side by side in the bars and look nothing alike in the boxes. boxStats() summarises a raw sample, rowsToBoxSpec() does it per group, and ChartSeries.errors annotates any existing mark without changing its type.
  • Axes, titles and styling - The chart hands the decisions back: a numeric x axis that spreads payload sizes the way the numbers do, pinned domains with a fixed tick interval and a formatter per axis, grid lines on or off, a shaded budget band, a vertical reference line, per-point markers and colours, a stepped dashed series on the right axis, a title / subtitle / caption, a legend on any side, and a tooltip snippet in single-series mode. Below it, 50,000 monitoring readings decimated to one point per pixel with LTTB or min / max - toggle it off to see the cost.