Bullet Chart

Summary

  • The Bullet Chart Style renders a compact, single-row chart in each cell of a numeric column
  • Each cell shows the actual value as a bar
  • Two optional extras include qualitative bands behind the (e.g. poor / ok / good), and a target marker
  • The chart axis spans from the resolved minimum to the maximum of the band scale
  • Targets can be hard-coded, taken from another column, or computed across the column (Col-Avg, Col-Median)

The Bullet Chart is a Styled Column which enables numeric columns to display a bullet graph in each cell.

Caution

Bullet Chart Styles can only be applied to Numeric Columns

The Chart is designed to compare a single quantitative measure (the cell value) against 2 measures:

  • a set of qualitative bands (the wizard requires at least one; the API allows none — see Bands)
  • an optional target measure

Hint

  • Bullet Charts work well for KPI columns where you want to answer, in one row of pixels, this question:
  • "How is this row's value doing against its target, and does it sit in the good or bad band?"
Deep Dive

Bullet Chart vs Percent Bar: Which Styled Column should I use?

Anatomy

A Bullet Chart cell is composed of three layers, drawn back-to-front:

  1. Bands - the qualitative scale (e.g. bad / good) drawn behind everything else using Cell Ranges
  2. Bar - the actual value of the cell, rendered as a horizontal bar drawn on top of the bands
  3. Target marker(s) - the comparative value, rendered as a marker on the bar

Note

  • The Bullet Chart's CellRanges colour the background bands and are drawn unconditionally
  • This matches the bullet-graph convention of using the bands as the qualitative scale
  • By contrast, the Percent Bar's CellRanges which colour the bar based on the cell value

Styling the Chart

There are many elements that can be defined and configured when creating a Bullet Chart Style.

Bands

The qualitative bands behind the bar are defined using the CellRanges property.

Each band has 3 properties:

  • a minimum value
  • a maximum value
  • an associated colour

There are 2 types of Ranges supported (just like with the Percent Bar Style):

  • Numeric - hard-coded numbers, or the dynamic endpoints Col-Min, Col-Max, Col-Avg, Col-Median
  • Percentage - 0-100 values that resolve against the column's own min/max

Hint

  • A common pattern is to create 3 bands - red / amber / green
  • These classify each row's value as good / average / bad against a fixed scale

Col-Avg and Col-Median evaluated across all visible rows, and are recomputed when row data changes.

Note

  • This makes them useful as automatic band thresholds (e.g. "below average is red, above average is green")
  • But without having to know the actual numbers up front

Numeric Bands

Use Number bands when thresholds are absolute values — fixed numbers or dynamic endpoints such as Col-Min, Col-Avg and Col-Max.

Bullet Chart: Number Bands
Fork
  • GitHub Stars — three Number bands (Col-MinCol-Avg100,000Col-Max) drawn behind the bar; all bands stay visible
  • Fixed target at 100,000 (line marker); the bar shows each row's stars on the full axis
  • Sorted descending on GitHub Stars

Percentage Bands

Use Percentage bands when each band is a slice of the column's value span (0100), so you can label "bottom third / middle / top third" without knowing the underlying numbers.

Bullet Chart: Percentage Bands
Fork
  • Closed PRs — three Percentage bands (033, 3366, 66100) resolved against the column's value span
  • Target is Col-Avg (triangle marker) — recomputes when visible data changes

Chart Axis

For each cell, AdapTable resolves the chart axis used to position the bar and markers.

The logic differs based on whether Cell Ranges are provided (the normal case and required in the wizard) or are omitted (possible only in AdapTable Initial State or when using the API):

CellRangesChart axisBackground
SetResolved min of the first bandmax of the last band. All bands are drawn on that span; the bar and target markers are positioned with clamp along it.Coloured bands behind the bar
OmittedColumn Col-MinCol-Max across visible rowsFlat BackColor (default transparent) no bands

Hint

  • When you omit Cell Ranges, set BackColor to tint the chart area
  • Use this API-only pattern when you want a bullet bar + target without a qualitative scale

Note

  • This is why a value can sit in the "green" band visually while the bar is pinned to the end of the track
  • The bar reflects position on the full axis, not "which band matched" (unlike Percent Bar)

Bar

The cell's value is rendered as a filled bar on top of the bands.

The Bar group contains 2 properties to configure how this bar will look:

PropertyDescription
Bar.ColorColour of the bar (defaults to var(--ab-color-primary))
Bar.HeightBar thickness in px when horizontal (defaults to 8); interpreted as bar width when vertical

Targets

Each cell can have one or more targets displayed as markers on the bar.

Targets are configured through the TargetProperties group, which has 2 properties:

  • Target — the resolvable target value, or an array of them
  • Marker — the chart-level default marker style (shared by every target unless overridden per-target)

Target can be one of 4 potential values:

  • a hard-coded number — e.g. Target: 100000 (every row uses the same target)
  • the id of another column — e.g. Target: 'forecast' (each row uses its own row's value)
  • 'Col-Avg' or 'Col-Median' — a value computed across the column's visible rows
  • an object: { Value: ..., Marker: { Shape, Color, Size }, Label? } (a BulletChartTargetDefinition) to override the marker style or supply a Label shown in the tooltip beside that target's value
Bullet Chart: Column Target
Fork
  • Open Issues — the bar is open issues; the target is Closed Issues on the same row (TargetProperties: { Target: 'closed_issues_count' })
  • Three numeric bands classify open-issue counts; the marker moves per row

Array of Targets

You can also pass an array as TargetProperties.Target to render several markers in the same cell.

Hint

This is useful for comparing against both a primary target and a stretch goal

TargetProperties: {
  Target: [
    { Value: 'forecast', Marker: { Shape: 'Line', Color: 'gray' } },
    { Value: 'stretch_target', Marker: { Shape: 'Diamond', Color: 'gold' } },
  ],
},
Bullet Chart: Multiple Targets
Fork
  • GitHub StarsTargetProperties.Target is an array: fixed goal (100,000, line) and column median (diamond), each with its own Marker and tooltip Label
  • Hover for cell value and axis percentage; compare marker shapes side by side

Marker Shapes

The Shape of the Marker can also be configured.

This is done using the TargetProperties.Marker.Shape property (or the Marker.Shape of a per-target BulletChartTargetDefinition), which supports 4 values:

  • 'Line' (the default) - a thin vertical line crossing the bar
  • 'Triangle' - a downward-pointing triangle
  • 'Dot' - a filled circle
  • 'Diamond' - a filled diamond

Note

Markers use the unified BarChartMarker shape ({ Shape, Color, Size }) shared with Range Bar and Percent Bar.

The Multiple Targets demo shows Line and Diamond markers in the same cell.

Negative Values

For columns with negative values, you can configure the bar to grow from a non-zero origin.

This is done via the Origin property :

ValueBehaviour
'Auto' (default)Bar grows from the chart's leading edge unless any cell value or band endpoint is negative, in which case it grows from 0 (centred axis)
'Zero'Bar always grows from 0; positive values extend toward Max, negative values extend toward Min
numberBar grows from that fixed origin

Caution

number is only available when creating the Bullet Chart via API or Initial State, and not in the UI Wizard

Hint

  • For variance columns ("actual vs forecast") set Origin to 'Zero'
  • This renders a centred bar that extends to the right for over-performance and to the left for under-performance
Bullet Chart: Negative Values
Fork
  • Issue ChangeOrigin: 'Auto' with bands Col-Min0 and 0Col-Max; bar grows left or right from 0
  • Target at 0 (line); cell value shown below the chart
  • Sorted ascending on Issue Change

Vertical Bars

By default Bullet Charts are drawn horizontally (bands and bar run left-to-right).

However it is possible to draw the chart vertically by setting the Orientation property to 'Vertical'.

AdapTable will then render the Bullet Chart in vertical mode as follows:

  • Bands and the bar stack vertically; lower values sit at the bottom of the cell.
  • Line markers are drawn horizontally across the bar.
  • Triangle markers rotate 90° so the apex points right.
  • Bar.Height is reinterpreted as the bar's short-axis size (i.e. its width in vertical mode).

Note

The same property is used deliberately, so that existing configurations migrate cleanly

BulletChartStyle: {
  Orientation: 'Vertical',
  RangeValueType: 'Percentage',
  CellRanges: [
    { Min: 0, Max: 50, Color: 'rgba(220, 53, 69, 0.35)' },
    { Min: 50, Max: 100, Color: 'rgba(40, 167, 69, 0.35)' },
  ],
  TargetProperties: {
    Target: 'Col-Avg',
  },
  Bar: {
    // In vertical mode `Bar.Height` is interpreted as the bar's *width*
    // (its short axis); the long axis stretches to fill the cell.
    Height: 10,
  },
}

Hint

  • Vertical bullet charts need a tall row height to be readable - we recommend at least 60px
  • AG Grid row height is a per-grid setting; set gridOptions.rowHeight (or use getRowHeight for per-row variation)
Bullet Chart: Vertical
Fork
  • GitHub WatchersOrientation: 'Vertical'; percentage bands and Col-Avg target (triangle points right in vertical mode)
  • gridOptions.rowHeight is 72 so the chart has room; Bar.Height is the bar width in vertical mode

Styling the Cell

As with all Styled Columns, you can style the cell chrome around the chart — companion text, tooltip, and font — separately from the bullet itself (bands, bar, targets, origin, orientation — see Styling the Chart).

Cell Text

Two text tokens can be drawn around the chart — independently, and each at its own position. They are configured under the CellTextProperties group:

PropertyTypeDescription
CellTextLayout.CellValueBarChartCellTextPlacementPlacement of the formatted cell value.
CellTextLayout.PercentValueBarChartCellTextPlacementPlacement of the percent value (cell value's position along the chart axis, as 0–100%; see Percentage Value).

A BarChartCellTextPlacement is { Horizontal, Vertical } where:

  • Horizontal'Left' (default), 'Center' or 'Right'
  • Vertical'Above', 'Below' (default) or 'Merged' (overlaid on the chart)

Note

  • A token is rendered only when its key is present in CellTextLayout
  • When both tokens land on the same horizontal slot at the same vertical position they are concatenated with a single space (Cell Value first, then Percent Value)
  • The new model lets you independently place the value above the bar (e.g. CellValue: { Horizontal: 'Left', Vertical: 'Above' }) and the percentage merged onto it (e.g. PercentValue: { Horizontal: 'Right', Vertical: 'Merged' })

Hint

Leave CellTextProperties unset to show the chart only

Percentage Value

The percent value shows where the cell value sits along the chart axis for that row.

This is calculated using the resolved band scale or column min/max:

clamp((value  min) / (max  min), 0, 1) × 100

AdapTable displays it as a whole-number percent (e.g. 67%).

Caution

  • The percentage is always clamped to 0–100% for display, even when the bar length is clamped at the axis edge
  • It is not the column's own min/max percentile (as in the Gradient style); it is always relative to that cell's chart axis

Tooltip

The cell can also be provided with a configurable AG Grid Cell Tooltip, via the ToolTipText property.

It accepts the tokens 'CellValue' and/or 'PercentageValue'.

Note

When both are enabled in the tooltip, the percent is appended in parentheses (e.g. 142.50 (67%))

Font

The Font property applies optional font styling to companion text rendered through CellTextProperties.

Note

  • When set, it overrides matching Format Column font properties on those cells
  • The wizard exposes the shared Font editor on the Style step whenever at least one Cell Display option is checked
Bullet Chart: Cell Text
Fork
  • Closed IssuesCellTextProperties: { CellTextLayout: { CellValue: { Horizontal: 'Center', Vertical: 'Merged' } } } (white bold from Format Column)
  • Tooltip shows value and percentage along the chart axis (ToolTipText)
Deep Dive

What happens if AdapTable cannot draw a valid scale in the Cell

Row Scope

Users can decide which kinds of rows will include the Bullet Chart Style.

Find Out More

See Styled Column Row Scope for details of the types of rows which can be included / excluded from a Styled Column

Defining Bullet Charts

Bullet Chart Styles are defined as part of the Styled Column Initial State.

Developer Guide

Providing a Bullet Chart Style in Styled Column State

const initialState: InitialState = {
  StyledColumn: {
    StyledColumns: [
      {
        Name: 'Github Stars KPI',
        ColumnId: 'github_stars',
        BulletChartStyle: {
          RangeValueType: 'Number',
          CellRanges: [
            {
              Min: 'Col-Min',
              Max: 'Col-Avg',
              Color: 'rgba(220, 53, 69, 0.35)',
            },
            {
              Min: 'Col-Avg',
              Max: 100000,
              Color: 'rgba(255, 193, 7, 0.35)',
            },
            {
              Min: 100000,
              Max: 'Col-Max',
              Color: 'rgba(40, 167, 69, 0.35)',
            },
          ],
          TargetProperties: {
            Target: 100000,
            Marker: {
              Shape: 'Line',
              Color: 'var(--ab-color-foreground)',
              Size: 2,
            },
          },
          Bar: {
            Color: '#07c',
            Height: 8,
          },
          CellTextProperties: {
            CellTextLayout: {
              CellValue: { Horizontal: 'Center', Vertical: 'Merged' },
            },
          },
        },
      },
    ],
  },
};
1
Provide ColumnId, Name and add the Style
  • Supply ColumnId of the Styled Column
  • Give the Styled Column a unique Name
  • Add a BulletChartStyle object
2
Add Bands via CellRanges

The CellRanges array defines the qualitative scale behind the bar.

Each band has Min, Max and Color. Min / Max can be:

  • a number
  • a percentage (when RangeValueType is 'Percentage')
  • a dynamic endpoint: Col-Min, Col-Max, Col-Avg, Col-Median
3
Add Targets via TargetProperties

The TargetProperties group places markers on the bar:

  • TargetProperties.Target — a hard-coded number, a column id, Col-Avg / Col-Median, or an array of any of these (with optional per-target marker overrides via BulletChartTargetDefinition)
  • TargetProperties.Marker — chart-level default marker style ({ Shape, Color, Size })
4
Style the Bar and Background
  • Bar.Color — colour of the actual bar (defaults to var(--ab-color-primary))
  • Bar.Height — bar thickness in px (defaults to 8); interpreted as the bar's width in vertical mode
  • BackColor — flat background when CellRanges is omitted
5
(Optional) Cell Text, Tooltip and Font
  • CellTextProperties.CellTextLayout — independent { Horizontal, Vertical } placement for CellValue and PercentValue tokens
  • ToolTipText — tokens 'CellValue' / 'PercentageValue' (see Percentage Value)
  • Font — optional companion-text styling

Using Bullet Charts

Bullet Chart Styles can be created at run-time using the Styled Column UI Wizard from:

  • the Styled Column section in the Settings Panel
  • Create Bullet Chart / Edit Bullet Chart in the Column Menu on a numeric column
UI Step by Step Guide

Creating a Bullet Chart Column Style using the Styled Column Wizard

FAQ

Can I have multiple targets in one cell? Yes - pass an array to TargetProperties.Target. Each entry can be a number, a Column Id, a dynamic endpoint, or an object with its own Marker override.

Can the target be different per row? Yes - pass a column id as TargetProperties.Target (or Value of a BulletChartTargetDefinition). The target marker is then resolved from each row's value in that column.

What happens if a value is outside the band range? The bar is clamped to the chart axis (lowest resolved band Min → highest resolved band Max). There is no Range Bar-style overflow mode — off-scale values appear as a full-length bar at the nearest edge.

Can I use the column min/max instead of bands? Yes — omit CellRanges in initialState / API and the bar scales across the column's visible min/max with a BackColor background. The wizard always requires at least one band; this pattern is API-only.

What happens if the Styled Column is suspended? When IsSuspended is true, AdapTable stops using the Bullet Chart renderer for that column and shows normal formatted cell values instead.

What if a target column has no value on a row? That target marker is skipped for the row; the bar and bands still render if the axis is valid. See What happens if AdapTable cannot draw a valid scale in the Cell above.

Can the underlying cell value still be shown? Yes — set CellTextProperties.CellTextLayout.CellValue to a { Horizontal, Vertical } placement. Use Vertical: 'Merged' to overlay the value on top of the bar. This pairs well with column formatting that sets the foreground colour.

Why does my chart look the same in light and dark mode? By default Bar.Color resolves to --ab-color-primary (the theme's brand colour) and TargetProperties.Marker.Color resolves to --ab-color-foreground (the theme's text colour), so they automatically follow the active theme. Override them with explicit colours if you need pixel-exact control.

Can I draw the chart vertically? Yes - set Orientation to 'Vertical' so lower values appear at bottom of the cell and higher values at the top. Vertical bullet charts need tall row height to be readable (we recommend at least 60px - see Vertical Bars above).