Skip to content
GitHub

ChartBullet

ChartBullet manifests describe IBCS bullet graphs: one horizontal row per KPI with a solid actual bar and a target marker. The default mode applies the IBCS improvements over the classic Stephen Few bullet graph — normalized targets (every row is scaled to fractions of its target, so one continuous target line spans all rows and KPIs become visually comparable) and integrated variance bars between actual and target in the IBCS variance colors. The classic look with per-row scales and qualitative gray bands is opt-in.

apiVersion: bino.bi/v1alpha1
kind: ChartBullet
metadata:
  name: kpi_overview
spec:
  dataset: kpis
  actual:                     # measure token or object; omitted = auto (ac1)
    measure: ac1
    label: "AC"
    unit: "EUR k"             # rendered once as "in EUR k" in the header
  target:                     # omitted = auto (pl1 > pp1 > fc1)
    measure: pl1
    label: "Plan"
  normalize: target           # target (default, IBCS) | none (classic)
  variances: auto             # auto (default) | none
  ranges: [0.6, 0.9]          # classic mode only: max 2 gray bands as fractions of target
  level: auto                 # auto | rowgroup | category | subcategory
  order: ac1                  # auto | hierarchy column | scenario slot
  orderDirection: desc        # asc | desc
  limit: 0                    # max KPI rows, 0 = unlimited (truncates, no REST row)
  labels:
    show: auto                # auto | none
    decimals: 1
  filter: "rowGroup = 'Revenue'"
  chartTitle: "KPI overview vs. plan"
  scale: auto                 # "" | none | auto | 0.5 | 1.2 | …
  selectedStyle: corporate-style
  ruleset: corporate-rules

The actual and target mappings accept either a bare scenario slot or an object whose measure property is a slot:

  • Scenario slots: ac1ac4, pp1pp4, fc1fc4, pl1pl4 — the row columns of the dataset.
  • Variance tokens are not allowed — the bullet variance is implicit (actual vs. target), so dac1_pl1-style tokens have no meaning here.

A bare string is shorthand for the object form: actual: ac1 equals actual: { measure: ac1 }.

Both measures auto-detect when omitted: actual prefers ac1 (else the first available scenario), target prefers pl1, then pp1, then fc1. A dataset without any target scenario renders plain actual bars with a warning.

One KPI row aggregates all dataset rows sharing the same level value (plain SUM, so cost KPIs show positive magnitudes). Values are drawn as delivered (no auto-SI scaling).

  • level picks the hierarchy column that identifies a KPI row (auto uses the deepest populated level of rowGroupcategorysubCategory).
  • normalize: target (the default) maps every row to fractions of its target: the target line aligns across rows at 100% and the rows become visually comparable. Rows whose target is missing or not positive cannot be normalized and render as label + value only, with a warning.
  • normalize: none draws the classic bullet: absolute values on per-row scales with tick strips and per-row target ticks.
  • The favorable/unfavorable reading of a variance follows the row's operation column: "-" marks cost-type KPIs and inverts the sentiment (an actual below a cost target is favorable).
  • dataset – required dataset name or array.
  • actual, target – optional measure mappings (slot or object with measure, label, unit); omitted values auto-detect.
  • ranges – optional qualitative bands as ascending fractions of the target, at most two (IBCS rejects a third band of arbitrary length). Classic mode only; ignored with a warning while normalize is target.
  • normalizetarget (default) or none.
  • variancesauto (default; variance bars in normalized mode) or none.
  • level – KPI row level.
  • order, orderDirection – row sorting; omitted uses the dataset's suggested order.
  • limit – max KPI rows; truncates without a REST aggregate (summing heterogeneous KPIs would be meaningless). 0 means unlimited.
  • labels – value labels: show (auto or none) and decimals (0–4, default 1).
  • filter – optional AlaSQL WHERE fragment.
  • chartTitle – optional title.
  • scale – proportional font scaling, same semantics as the other charts (none, auto, or a fixed factor); bullet charts auto-fit against the parent height.
  • selectedStyle – optional name of a ComponentStyle to apply; merged over the _system and _default styles.
  • ruleset – optional name of a RuleSet to apply, or inherited-closest / inherited-page to inherit the surrounding layout's rule set. The target marker's treatment follows the target scenario's rule-set family (PL solid, FC dashed, PP gray).

Everything auto-detects — actual ac1, target pl1 > pp1 > fc1, level and order from the dataset:

---
apiVersion: bino.bi/v1alpha1
kind: ChartBullet
metadata:
  name: kpi_overview
spec:
  dataset: kpis
---
apiVersion: bino.bi/v1alpha1
kind: ChartBullet
metadata:
  name: revenue_bullet
spec:
  dataset: revenue_by_region
  chartTitle: "Revenue vs. plan by region"
  actual: ac1
  target:
    measure: pl1
    label: "Plan"
  order: ac1
  orderDirection: desc

Per-row scales, up to two gray bands, no variance bars:

---
apiVersion: bino.bi/v1alpha1
kind: ChartBullet
metadata:
  name: revenue_bullet_classic
spec:
  dataset: revenue_by_region
  chartTitle: "Revenue vs. plan (classic bullet)"
  actual: ac1
  target: pl1
  normalize: none
  ranges: [0.6, 0.9]
  variances: none
  labels:
    decimals: 0
AttributeTypeRequiredDefaultDescription
apiVersionstringyesMust be bino.bi/v1alpha1.
kindstringyesMust be ChartBullet.
metadata.namestringyesUnique identifier.
metadata.labelsobjectnoKey-value pairs for categorization and constraint matching.
metadata.annotationsobjectnoArbitrary key-value metadata, not used by the system.
metadata.descriptionstringnoFree-form description.
metadata.constraintsarraynoConditional inclusion rules. See Constraints.
AttributeTypeRequiredDefaultDescriptionSample
spec.datasetstring or objectyesDataset reference (name or inline definition). Maps to the datasets HTML attribute.dataset: kpis
spec.actualstring or objectnoauto (ac1)Actual-value measure mapping (plain scenario slot). Maps to the actual HTML attribute.actual: ac1
spec.targetstring or objectnoauto (pl1 > pp1 > fc1)Target measure mapping (plain scenario slot). Maps to the target HTML attribute.target: { measure: pl1, label: "Plan" }
spec.rangesarray of numbersnoUp to two ascending positive fractions of the target (classic mode gray bands). Maps to the ranges HTML attribute.ranges: [0.6, 0.9]
spec.normalizestringnotargetTarget normalization. Values: target, none.normalize: none
spec.variancesstringnoautoVariance bars. Values: auto, none.variances: none
spec.levelstringnoautoKPI row level. Values: auto, rowgroup, category, subcategory.level: category
spec.orderstringnoautoSort key: auto, a hierarchy column, or a scenario slot.order: ac1
spec.orderDirectionstringnoascSorting direction. Values: asc, desc. Maps to the order-direction HTML attribute.orderDirection: desc
spec.limitintegerno0Max KPI rows (truncates, no REST aggregate). 0 means unlimited.limit: 6
spec.labelsobjectnoshow: auto, decimals: 1Value labels: show (auto or none) and decimals (0–4).labels: { decimals: 0 }
spec.filterstringno""AlaSQL WHERE clause fragment to filter rows.filter: "rowGroup = 'Revenue'"
spec.chartTitlestringno""Custom chart title. Maps to the chart-title HTML attribute.chartTitle: "KPI overview"
spec.scalestring or numbernoauto-scale with warningProportional scaling. "none": no scaling. "auto": auto-scale silently. Positive number: fixed factor.scale: auto
spec.selectedStylestringnoName of a ComponentStyle manifest to apply. Maps to the selected-style HTML attribute.selectedStyle: corporate-style
spec.rulesetstringnoName of a RuleSet manifest to apply, or inherited-closest / inherited-page. Maps to the ruleset HTML attribute.ruleset: corporate-rules

See ChartStructure for general bar charts with explicit scenario and variance columns.