Skip to content

Range Bar and Range Area

Range series: instead of yField, a yLowField / yHighField pair.

Range Area

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Temperature range' },
    series: [{ type: 'range-area', xField: 'month', yLowField: 'min', yHighField: 'max', name: 'Min–Max, °C' }],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { month: 'Jan', min: -12, max: -2 },
    { month: 'Feb', min: -10, max: 0 },
    { month: 'Mar', min: -4, max: 6 },
    { month: 'Apr', min: 2, max: 14 },
    { month: 'May', min: 8, max: 21 },
    { month: 'Jun', min: 13, max: 26 },
    { month: 'Jul', min: 15, max: 29 },
    { month: 'Aug', min: 13, max: 27 },
    { month: 'Sep', min: 8, max: 20 },
    { month: 'Oct', min: 2, max: 11 },
    { month: 'Nov', min: -4, max: 4 },
    { month: 'Dec', min: -9, max: -1 },
  ];
}

Range Bar

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Salary ranges' },
    subtitle: { text: 'thousand ₽ per month' },
    series: [{ type: 'range-bar', xField: 'role', yLowField: 'from', yHighField: 'to', name: 'Range' }],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { role: 'Junior', from: 80, to: 150 },
    { role: 'Middle', from: 160, to: 260 },
    { role: 'Senior', from: 250, to: 400 },
    { role: 'Lead', from: 320, to: 480 },
  ];
}

Horizontal range bars

direction: 'horizontal' flips the chart: categories move to the vertical axis.

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Salary ranges' },
    subtitle: { text: 'thousand ₽ per month' },
    series: [
      {
        type: 'range-bar',
        xField: 'role',
        yLowField: 'from',
        yHighField: 'to',
        name: 'Range',
        direction: 'horizontal',
      },
    ],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { role: 'Junior', from: 80, to: 150 },
    { role: 'Middle', from: 160, to: 260 },
    { role: 'Senior', from: 250, to: 400 },
    { role: 'Lead', from: 320, to: 480 },
  ];
}

Per-bar colour (Gantt)

fill accepts a callback ({ low, high, datum, index }) => color — colour each bar individually, e.g. a Gantt timeline painted by task status from a single series:

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

// Colour each task bar by its status — a Gantt-style timeline from a single range-bar series.
const STATUS_COLORS: Record<string, string> = {
  done: '#22c55e',
  running: '#3b82f6',
  failed: '#ef4444',
  queued: '#94a3b8',
};

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Pipeline run' },
    subtitle: { text: 'task timeline, hours' },
    series: [
      {
        type: 'range-bar',
        xField: 'task',
        yLowField: 'start',
        yHighField: 'end',
        direction: 'horizontal',
        cornerRadius: 3,
        fill: ({ datum }) => STATUS_COLORS[String(datum.status)] ?? '#94a3b8',
      },
    ],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { task: 'extract', start: 0, end: 3, status: 'done' },
    { task: 'validate', start: 3, end: 5, status: 'done' },
    { task: 'transform', start: 5, end: 11, status: 'running' },
    { task: 'notify', start: 8, end: 10, status: 'failed' },
    { task: 'load', start: 11, end: 14, status: 'queued' },
    { task: 'report', start: 14, end: 16, status: 'queued' },
  ];
}

Range labels

label.formatter({ low, high, datum }); placements are the same as for bar — here center inside the bar with auto contrast:

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Ranges with labels' },
    series: [
      {
        type: 'range-bar',
        xField: 'city',
        yLowField: 'min',
        yHighField: 'max',
        name: 'Temperature, °C',
        label: {
          enabled: true,
          placement: 'center',
          formatter: ({ low, high }) => `${low}…${high}`,
        },
      },
    ],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { city: 'Moscow', min: -8, max: 2 },
    { city: 'Sochi', min: 4, max: 12 },
    { city: 'Novosibirsk', min: -16, max: -6 },
    { city: 'Kazan', min: -10, max: 0 },
    { city: 'Vladivostok', min: -7, max: 1 },
  ];
}

Combining with a mean line

Range-area as the background + line on top, with a shared tooltip:

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Range + average line' },
    series: [
      {
        type: 'range-area',
        xField: 'month',
        yLowField: 'min',
        yHighField: 'max',
        name: 'Range, °C',
        fillOpacity: 0.25,
      },
      { type: 'line', xField: 'month', yField: 'avg', name: 'Average', strokeWidth: 2.5 },
    ],
    tooltip: { mode: 'shared', range: 'nearest' },
  };
}
ts
export function getData() {
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  return months.map((month, i) => {
    const mid = 8 + 14 * Math.sin(((i - 3) / 12) * Math.PI * 2);
    return {
      month,
      min: Math.round(mid - 5 - (i % 3)),
      max: Math.round(mid + 6 + ((i + 1) % 3)),
      avg: Math.round(mid),
    };
  });
}
OptionTypeDescription
yLowFieldstringrange bounds
yHighFieldstringrange bounds
direction (bar)'vertical' | 'horizontal'bar direction (vertical)
fillColorValue | (params) => ColorValuefill; callback colours per datum
fillstylesfill
fillOpacitystylesfill
stroke (area)stylesoutline lines
strokeWidth (area)stylesoutline lines
cornerRadius (bar)Pixelscorner rounding
groupGap (bar)Fractiongap between bars of one group (0.2)

Full list of options

OptionTypeDefaultDescription
label.enabledbooleanfalseshow value labels
label.placementouter/center/inner-* (17 placements)'top'label placement
label.formatter({ low, high, datum }) => stringvaluelabel content
label.fontSizePixels11label font size
label.fontWeightstring | numbernormalfont weight
label.fontFamilystringtheme fontfont family
label.colorColorValueforeground; inside — auto contrasttext color

Options

Options common to all series (name, showInLegend, tooltip.renderer, …) are covered in Common series options.

A range mark spans two values, so tooltip.renderer — on the range bar and the range area alike — receives RangeTooltipRendererParams: { datum, xValue, low, high, seriesName, color }.

js
tooltip: { renderer: ({ low, high }) => `${String(low)} – ${String(high)}` },