OlliVisSpec
OlliVisSpec is Olli's normalized description of a data visualization. It comes in two forms: UnitOlliVisSpec for a single chart, and MultiOlliVisSpec for layered or concatenated views.
You rarely write an OlliVisSpec by hand — the Vega-Lite adapter generates it for you. But understanding the shape is useful for debugging, writing tests, or building a custom adapter.
UnitOlliVisSpec
A single chart view.
interface UnitOlliVisSpec {
data: OlliDataset;
fields?: OlliFieldDef[];
structure?: OlliNode | OlliNode[];
mark?: OlliMark;
axes?: OlliAxis[];
legends?: OlliLegend[];
guides?: OlliGuide[];
facet?: string;
selection?: Selection;
title?: string;
description?: string;
}| Property | Type | Required | Description |
|---|---|---|---|
data | OlliDatum[] | yes | The dataset. Each datum is a Record<string, OlliValue>. |
fields | OlliFieldDef[] | no | Field definitions with types, labels, binning, time units. Auto-inferred if omitted. |
structure | OlliNode | OlliNode[] | no | How the tree is organized — groupby, predicate, and annotation nodes. Auto-inferred from axes/legends if omitted. |
mark | OlliMark | no | A mark type string or OlliMarkDef object. Used for chart-type descriptions. See OlliMark. |
axes | OlliAxis[] | no | X and Y axis guides with field, title, scale type, and tick values. |
legends | OlliLegend[] | no | Color, opacity, or size legend guides. |
guides | OlliGuide[] | no | Generic guides that don't fit axis or legend. |
facet | string | no | Field name for faceting. The top-level groupby becomes facet views. |
selection | Selection | no | Pre-filter applied to the data before lowering. |
title | string | no | Chart title. |
description | string | no | Longer description, announced at the root node. |
MultiOlliVisSpec
Multiple views composed together.
interface MultiOlliVisSpec {
operator: 'layer' | 'concat';
units: UnitOlliVisSpec[];
}| Property | Type | Required | Description |
|---|---|---|---|
operator | 'layer' | 'concat' | yes | 'layer' overlays views (same axes). 'concat' places them side by side. |
units | UnitOlliVisSpec[] | yes | The individual views. |
Type guard
function isMultiSpec(spec: OlliVisSpec): spec is MultiOlliVisSpecOlliMark
type OlliMarkType = 'point' | 'bar' | 'line' | 'area' | 'rect' | 'tick' | 'arc';
interface OlliMarkDef {
type: OlliMarkType;
innerRadius?: number;
stack?: 'stacked' | 'grouped';
}
type OlliMark = OlliMarkType | OlliMarkDef;The mark can be a plain type string ('bar') or an object with additional properties ({ type: 'arc', innerRadius: 50 }). Mark-level properties like innerRadius and stack live on the OlliMarkDef object rather than the top-level spec.
Use the getMarkType helper to extract the type string from either form:
import { getMarkType } from 'olli-vis';
getMarkType('bar'); // 'bar'
getMarkType({ type: 'arc', innerRadius: 50 }); // 'arc'
getMarkType(undefined); // undefinedThe mark type drives chart-type inference in description tokens. A point mark with two quantitative axes becomes "scatterplot"; a rect with a color legend becomes "heatmap"; an arc mark becomes "pie chart" or "donut chart" depending on innerRadius.
Value types
type OlliValue = string | number | Date;
type OlliDatum = Record<string, OlliValue>;
type OlliDataset = OlliDatum[];Elaboration
When you call olliVis or lowerVisSpec, the spec is first passed through elaborateSpec:
function elaborateSpec(spec: OlliVisSpec): OlliVisSpecElaboration fills in defaults:
- If
fieldsis missing, it creates oneOlliFieldDefper key indata[0]. - If any field lacks a
type, it runs type inference on the data column. - If
structureis missing, it infers a tree structure from the axes, legends, and guides.
This means a minimal spec only needs data, mark, and axes — everything else is derived.
Next
- Fields, Axes & Legends — field definitions and guide types.
- Structure Nodes — how the tree structure is specified.
- Vis Lowering — how specs become hypergraphs.