Line Graphs¶
Line graphs connect values across an ordered axis, usually time, to emphasize continuity, direction, rate of change, and overall shape; this family includes single- or multi-series lines and slope graphs. They are most useful when the main question is how something changes over time rather than how big isolated categories are.
Dataface line graphs use a small set of top-level shorthand fields together with style. In most cases, you only need query, type: line, x, and y to get started.
A chart's control surface is the full set of authored properties available on a single chart. In Dataface, that surface is primarily top-level chart fields plus typed style objects.
This page is intentionally family-oriented rather than exhaustive. For the implementation-backed source of truth, including default ownership and lower-level property coverage, see the YAML Schema Reference.
Minimum Required for a Line Graph¶
These are the minimum fields required to render a basic line graph in Dataface.
| Dataface field | Maps to Vega-Lite | Allowed values | Notes |
|---|---|---|---|
query |
data.values |
Query name or query reference | Supplies the dataset. |
type: line |
mark.type: "line" |
Literal line |
Selects the line mark. |
x |
encoding.x.field |
Field name | Ordered dimension, usually time. |
y |
encoding.y.field |
Field name | Numeric measure to plot. |
Minimum Example¶
source: examples_db
charts:
revenue_trend_minimal:
query:
sql: |
SELECT date, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Daily Revenue
x: date
y: revenue
rows:
- revenue_trend_minimal
Top-Level Chart Fields¶
These are the top-level chart properties you set directly on a line graph before you get into nested properties under style.
| Dataface field | Maps to Vega-Lite | Allowed values | Notes |
|---|---|---|---|
query |
data.values |
Query name or query reference | Query results become the plotted dataset. |
type: line |
mark.type: "line" |
Literal line |
Selects the line mark. |
x |
encoding.x.field |
Field name | Usually a temporal or ordered field. |
y |
encoding.y.field |
Field name or list of field names | A list creates layered multi-metric lines. |
title |
title.text |
String | Chart title. |
description |
metadata | String | Available for tooling and docs. |
color |
encoding.color.field |
Field name | Groups a line into multiple series. |
x_label |
encoding.x.title |
String | Custom x-axis title. |
y_label |
encoding.y.title |
String | Custom y-axis title. |
format |
encoding.y.format and encoding.y.axis.format |
Format string | Numeric formatting for the y channel. |
sort |
categorical axis sort | Sort object | Most useful when the x-axis is categorical. |
projection |
top-level projection |
Vega-Lite projection name | Available for Vega-Lite projection overrides. |
Multi-Series Line Graph¶
This example adds color to split one line into multiple series while keeping the top-level chart definition compact.
source: examples_db
charts:
revenue_by_product:
query:
sql: |
SELECT date, product, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date, product ORDER BY date, product
type: line
title: Revenue by Product
x: date
y: revenue
color: product
rows:
- revenue_by_product
Axis Labels, Formatting, and Styling¶
This example shows common top-level chart fields such as labels and numeric formatting.
source: examples_db
charts:
revenue_formatted:
query:
sql: |
SELECT date, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Revenue Over Time
x: date
y: revenue
x_label: Date
y_label: Revenue
style:
number_format: currency_whole
scale:
zero: false
axis:
grid:
visible: false
rows:
- revenue_formatted
Layered Multi-Metric Lines¶
When y is a list, Dataface creates a layered line graph. This is useful when you want to compare two measures that share the same ordered x-axis.
source: examples_db
charts:
revenue_and_units:
query:
sql: |
SELECT date, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Revenue And Units Sold
x: date
y: [revenue, units_sold]
rows:
- revenue_and_units
Style Fields¶
Use style for Dataface shorthand properties that affect presentational defaults such as legend visibility and grid lines.
| Dataface field | Maps to Vega-Lite | Allowed values | Notes |
|---|---|---|---|
style.legend.visible |
encoding.color.legend |
true or false |
Typed legend control. false hides the legend. |
style.axis.grid.visible |
axis grid visibility | true or false |
false hides grid lines. Use style.axis.grid.visible: false (nested under grid:). |
style.background |
chart SVG background wrapper | Color value | Applies a chart-level background fill behind the rendered SVG. |
Legend and Grid Lines¶
This example shows the small style surface for line graphs without changing the underlying data bindings.
source: examples_db
charts:
revenue_formatted:
query:
sql: |
SELECT date, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Revenue Over Time
x: date
y: revenue
x_label: Date
y_label: Revenue
style:
number_format: currency_whole
scale:
zero: false
axis:
grid:
visible: false
rows:
- revenue_formatted
Axis and Scale Style¶
Use style for axis and scale properties that shape how the line graph is framed and read.
| Dataface field | Maps to Vega-Lite | Allowed values | Notes |
|---|---|---|---|
style.axis_x |
config.axisX / encoding.x.axis |
AxisStyle object |
Per-axis styling (format, ticks, labels, grid, title). |
style.axis_y |
config.axisY / encoding.y.axis |
AxisStyle object |
Per-axis styling. |
style.scale |
config.scale |
ScaleStyle object |
Global scale config (zero, nice, domain, clamp). |
Axis and Scale Controls¶
This example uses style to control the y-axis scale and tick density.
source: examples_db
charts:
revenue_formatted:
query:
sql: |
SELECT date, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Revenue Over Time
x: date
y: revenue
x_label: Date
y_label: Revenue
style:
number_format: currency_whole
scale:
zero: false
axis:
grid:
visible: false
rows:
- revenue_formatted
Log Scale¶
Set style.scale.type: log to plot a quantitative axis on a logarithmic scale — useful when values span multiple orders of magnitude (e.g. exponential growth). Log scales are undefined at zero and for negative numbers; Dataface passes type: log straight through to Vega-Lite without validating the domain, so a zero or negative value in the data produces a broken or empty render rather than a Dataface-level error. Only use scale.type: log on a measure you know is strictly positive.
source: examples_db
charts:
revenue_log:
query:
sql: |
SELECT date, SUM(revenue) AS revenue FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Revenue Over Time (Log Scale)
x: date
y: revenue
x_label: Date
y_label: Revenue
style:
number_format: currency_whole
scale:
type: log
rows:
- revenue_log
Endpoint Labels¶
Set style.endpoint_labels.visible: true on a multi-series line graph to move the series names off the side legend and onto the chart, anchored to each line's final point. The chart pane and label pane sit side-by-side in an hconcat, with one label per series.
| Dataface field | Allowed values | Notes |
|---|---|---|
style.endpoint_labels.visible |
true or false |
Opt-in feature toggle. Defaults to false on every built-in theme — set per-chart when you want it. |
When the label pane is on, the categorical legend turns off automatically — the two would encode the same series→colour mapping twice. The y-axis also auto-flips to the left so it doesn't collide with the right-edge label pane.
On narrow cards, endpoint-label text compacts to fit the available width while its automatic vertical spacing stays readable for closely ending series.
Endpoint labels require a color channel (a multi-series chart); on single-series lines there's only one series to name, so the feature is a no-op.
source: examples_db
charts:
revenue_by_product:
query:
sql: |
SELECT date, product, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date, product ORDER BY date, product
type: line
title: Revenue by Product
x: date
y: revenue
color: product
style:
endpoint_labels:
visible: true
rows:
- revenue_by_product
Smoothing & Step Lines¶
style.marks.line.curve controls how adjacent points are joined, in place of
the default straight-segment interpolation:
| Value | Effect |
|---|---|
monotone |
A smooth curve that never overshoots the data — no wobble past a local min or max. A softer read than straight segments without misrepresenting the trend. |
step |
On a categorical (nominal/ordinal) x-axis, a full-band-width plateau per x-value instead of a diagonal segment. On a continuous (temporal/quantitative) x-axis, Vega-Lite's own native step interpolate (points at band centers). |
source: examples_db
charts:
revenue_smoothed:
query:
sql: |
SELECT date, SUM(revenue) AS revenue FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Daily Revenue (Smoothed)
x: date
y: revenue
style:
marks:
line:
curve: monotone
rows:
- revenue_smoothed
Step Lines¶
curve: step on a categorical x column draws a full-band-width plateau.
Adjacent plateaus are joined by a vertical bridge by default; set
connect: false to leave them as disconnected segments instead.
source: examples_db
charts:
revenue_by_product_step:
query:
sql: |
SELECT product, SUM(revenue) AS revenue FROM ecommerce_orders GROUP BY product ORDER BY revenue DESC
type: line
title: Product Revenue (Step)
x: product
y: revenue
style:
marks:
line:
curve: step
connect: false
rows:
- revenue_by_product_step
Halo¶
Multi-series lines that cross each other can be hard to trace right at the
crossing point. style.marks.line.halo_multiplier draws a knockout-colored
stroke behind each line, sized relative to the line's own stroke width, so
crossings stay legible. Set it to 0 to disable the halo.
Value Labels¶
Show the numeric value beside each data point on a line chart by enabling style.marks.line.labels.visible.
source: examples_db
charts:
revenue_labeled:
query:
sql: |
SELECT date, SUM(revenue) AS revenue FROM ecommerce_orders GROUP BY date ORDER BY date
type: line
title: Daily Revenue
x: date
y: revenue
style:
marks:
line:
labels:
visible: true
position: top # top | bottom | left | right | middle
format: ",.1f" # omit to inherit axis_quantitative.format
font:
color: "#6b7280"
size: 11
rows:
- revenue_labeled
Position values:
| Value | Placement |
|---|---|
top |
Above the point — default |
bottom |
Below the point |
left |
To the left of the point |
right |
To the right of the point |
middle |
Centered on the point |
dx/dy (pixel offsets) are also available under labels to nudge a label off its default position. Line and point charts share the same position vocabulary and Vega-Lite mapping.
Overlays (layers:)¶
Add a layers: list to a line chart to overlay additional marks — a bar for context, a
scatter reference, or a second line on a separate y-axis. The base line chart owns the
x-axis, frame, title, legend, and sort. Each layer contributes its own mark and legend
entry.
charts: trend_with_target: type: line x: month y: actual query: monthly layers: - type: line y: target label: Target axis_y: position: right title: Target style: stroke: width: 2 dash: [4, 2]
For a dual-axis example where the overlay draws from a separate query:
charts: signups_and_conversion: type: line x: month y: signups query: monthly_signups layers: - type: line y: conversion_pct label: Conversion (%) query: weekly_conversion axis_y: position: right title: Conversion (%) scale: domain: [0, 100]
Layer x-values from a separate query extend the base x-scale automatically — no x_domain field is needed or accepted.
Layer fields: type, y, label, color, query, x, axis_y, style (marks-only patch). sort: is base-only.
Authored Surface¶
Dataface line charts are authored with type: line plus top-level channels such as x, y, and color. Arbitrary Vega-Lite spec, mark, encoding, config, transform, params, and composition blocks are rejected on the authored surface. Use top-level Dataface fields and the typed style: object.