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:
- Bands - the qualitative scale (e.g. bad / good) drawn behind everything else using Cell Ranges
- Bar - the actual value of the cell, rendered as a horizontal bar drawn on top of the bands
- Target marker(s) - the comparative value, rendered as a marker on the bar
Note
- The Bullet Chart's
CellRangescolour 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
CellRangeswhich 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.
- GitHub Stars — three Number bands (
Col-Min→Col-Avg→100,000→Col-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 (0–100), so you can label "bottom third / middle / top third" without knowing the underlying numbers.
- Closed PRs — three Percentage bands (
0–33,33–66,66–100) 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):
CellRanges | Chart axis | Background |
|---|---|---|
| Set | Resolved min of the first band → max 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 |
| Omitted | Column Col-Min → Col-Max across visible rows | Flat BackColor (default transparent) no bands |
Hint
- When you omit Cell Ranges, set
BackColorto 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:
| Property | Description |
|---|---|
Bar.Color | Colour of the bar (defaults to var(--ab-color-primary)) |
Bar.Height | Bar 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 themMarker— 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? }(aBulletChartTargetDefinition) to override the marker style or supply a Label shown in the tooltip beside that target's value
- 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' } },
],
},- GitHub Stars —
TargetProperties.Targetis an array: fixed goal (100,000, line) and column median (diamond), each with its ownMarkerand 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 :
| Value | Behaviour |
|---|---|
'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 |
number | Bar 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
Originto'Zero' - This renders a centred bar that extends to the right for over-performance and to the left for under-performance
- Issue Change —
Origin: 'Auto'with bandsCol-Min…0and0…Col-Max; bar grows left or right from0 - 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.Heightis 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 usegetRowHeightfor per-row variation)
- GitHub Watchers —
Orientation: 'Vertical'; percentage bands andCol-Avgtarget (triangle points right in vertical mode) gridOptions.rowHeightis 72 so the chart has room;Bar.Heightis 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:
| Property | Type | Description |
|---|---|---|
CellTextLayout.CellValue | BarChartCellTextPlacement | Placement of the formatted cell value. |
CellTextLayout.PercentValue | BarChartCellTextPlacement | Placement 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) × 100AdapTable 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
- Closed Issues —
CellTextProperties: { 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' },
},
},
},
},
],
},
};- Supply
ColumnIdof the Styled Column - Give the Styled Column a unique
Name - Add a
BulletChartStyleobject
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
RangeValueTypeis'Percentage') - a dynamic endpoint:
Col-Min,Col-Max,Col-Avg,Col-Median
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 viaBulletChartTargetDefinition)TargetProperties.Marker— chart-level default marker style ({ Shape, Color, Size })
Bar.Color— colour of the actual bar (defaults tovar(--ab-color-primary))Bar.Height— bar thickness in px (defaults to 8); interpreted as the bar's width in vertical modeBackColor— flat background whenCellRangesis omitted
CellTextProperties.CellTextLayout— independent{ Horizontal, Vertical }placement forCellValueandPercentValuetokensToolTipText— 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).