The Line Chart widget renders multi-series line graphs with automatic scaling, legends, and smooth sub-cell rendering.
Basic Usage
import { ui } from "@rezi-ui/core";
ui.lineChart({
id: "sales-chart",
width: 60,
height: 20,
series: [
{
data: [10, 25, 15, 40, 30, 45, 35],
color: "#3b82f6",
label: "Revenue",
},
],
});
Props
Widget identifier for debugging.
Chart width in terminal columns.
Chart height in terminal rows.
series
LineChartSeries[]
required
Data series to plot. Each series has:
data: number[] - Y-axis values
color: string - Line color (hex or theme)
label?: string - Series name for legend
axes
{ x?: ChartAxis, y?: ChartAxis }
Axis configuration:
label?: string - Axis label
min?: number - Minimum value (auto if omitted)
max?: number - Maximum value (auto if omitted)
blitter
GraphicsBlitter
default:"braille"
Rendering mode. One of "braille", "sextant", "quadrant", "halfblock".
Note: "ascii" is not supported for line charts.
Show series legend below the chart.
Each series is an object with data, color, and optional label:
type LineChartSeries = {
data: readonly number[]; // Y-axis values
color: string; // Hex or theme color
label?: string; // Series name
};
Single Series
ui.lineChart({
id: "temperature",
width: 50,
height: 15,
series: [
{
data: [20, 22, 21, 24, 26, 25, 23],
color: "#ef4444",
label: "Temperature (°C)",
},
],
});
Multiple Series
ui.lineChart({
id: "comparison",
width: 60,
height: 20,
series: [
{
data: [10, 15, 12, 18, 16, 20, 19],
color: "#3b82f6",
label: "Product A",
},
{
data: [8, 12, 14, 11, 15, 17, 16],
color: "#10b981",
label: "Product B",
},
{
data: [5, 7, 9, 8, 10, 12, 14],
color: "#f59e0b",
label: "Product C",
},
],
showLegend: true,
});
Axis Configuration
Auto-Scaling (Default)
By default, axes auto-scale to fit data:
ui.lineChart({
width: 50,
height: 20,
series: [{ data: [10, 50, 30, 80], color: "#3b82f6" }],
// Y-axis: min=10, max=80 (computed)
});
Fixed Y-Axis Range
ui.lineChart({
width: 50,
height: 20,
series: [{ data: [10, 50, 30, 80], color: "#3b82f6" }],
axes: {
y: {
min: 0,
max: 100,
label: "Usage (%)",
},
},
});
Axis Labels
ui.lineChart({
width: 60,
height: 20,
series: [{ data: values, color: "#3b82f6" }],
axes: {
x: { label: "Time (hours)" },
y: { label: "Requests/sec" },
},
});
Blitter Modes
Braille (Default)
Smooth curves with 2×4 sub-cell resolution:
ui.lineChart({
width: 60,
height: 20,
series: [{ data: values, color: "#3b82f6" }],
blitter: "braille", // Default
});
Sextant
Block-based rendering with 2×3 resolution:
ui.lineChart({
width: 60,
height: 20,
series: [{ data: values, color: "#3b82f6" }],
blitter: "sextant",
});
Quadrant
Pixelated style with 2×2 resolution:
ui.lineChart({
width: 60,
height: 20,
series: [{ data: values, color: "#3b82f6" }],
blitter: "quadrant",
});
Halfblock
Horizontal bars with 1×2 resolution:
ui.lineChart({
width: 60,
height: 20,
series: [{ data: values, color: "#3b82f6" }],
blitter: "halfblock",
});
Examples
Real-Time Metrics
import { defineWidget } from "@rezi-ui/core";
type MetricsState = {
cpuHistory: number[];
memHistory: number[];
};
function metricsChart(state: MetricsState): VNode {
return ui.lineChart({
id: "metrics",
width: 70,
height: 25,
series: [
{
data: state.cpuHistory,
color: "#3b82f6",
label: "CPU %",
},
{
data: state.memHistory,
color: "#10b981",
label: "Memory %",
},
],
axes: {
y: { min: 0, max: 100, label: "Usage %" },
x: { label: "Time" },
},
showLegend: true,
});
}
Financial Data
function stockChart(prices: number[]): VNode {
return ui.column({ gap: 1 }, [
ui.text("Stock Price (Last 30 Days)", { variant: "heading" }),
ui.lineChart({
id: "stock",
width: 80,
height: 30,
series: [
{
data: prices,
color: prices[prices.length - 1] > prices[0] ? "#10b981" : "#ef4444",
label: "Price (USD)",
},
],
axes: {
y: { label: "Price" },
x: { label: "Days" },
},
}),
]);
}
Multi-Metric Dashboard
function dashboard(data: {
requests: number[];
errors: number[];
latency: number[];
}): VNode {
return ui.column({ gap: 2, p: 1 }, [
ui.text("API Metrics", { variant: "heading" }),
// Requests chart
ui.column({ gap: 0 }, [
ui.text("Request Volume", { style: { bold: true } }),
ui.lineChart({
id: "requests",
width: 70,
height: 15,
series: [
{ data: data.requests, color: "#3b82f6", label: "Requests/min" },
],
axes: { y: { min: 0 } },
}),
]),
// Errors chart
ui.column({ gap: 0 }, [
ui.text("Error Rate", { style: { bold: true } }),
ui.lineChart({
id: "errors",
width: 70,
height: 15,
series: [
{ data: data.errors, color: "#ef4444", label: "Errors/min" },
],
axes: { y: { min: 0 } },
}),
]),
// Latency chart
ui.column({ gap: 0 }, [
ui.text("Latency (p95)", { style: { bold: true } }),
ui.lineChart({
id: "latency",
width: 70,
height: 15,
series: [
{ data: data.latency, color: "#f59e0b", label: "ms" },
],
axes: { y: { min: 0 } },
}),
]),
]);
}
Comparison Chart with Legend
function comparisonChart(
actual: number[],
target: number[],
forecast: number[]
): VNode {
return ui.lineChart({
id: "comparison",
width: 80,
height: 30,
series: [
{ data: actual, color: "#3b82f6", label: "Actual" },
{ data: target, color: "#10b981", label: "Target" },
{ data: forecast, color: "#f59e0b", label: "Forecast" },
],
axes: {
y: { label: "Revenue ($M)" },
x: { label: "Quarter" },
},
showLegend: true,
});
}
Sparse Data Handling
function sparseChart(data: Array<number | null>): VNode {
// Filter out nulls and map to indices
const filtered = data
.map((val, i) => ({ val, i }))
.filter(({ val }) => val !== null);
return ui.lineChart({
id: "sparse",
width: 60,
height: 20,
series: [
{
data: filtered.map(({ val }) => val!),
color: "#3b82f6",
label: "Valid Points",
},
],
});
}
Data Point Limits
- Braille: Smooth up to ~500 points
- Sextant: Smooth up to ~400 points
- Quadrant: Smooth up to ~300 points
- Halfblock: Smooth up to ~200 points
For larger datasets, consider:
- Downsampling (e.g., show every Nth point)
- Rolling windows (show last N points)
- Aggregation (hourly → daily)
Downsampling Example
function downsample(data: number[], targetPoints: number): number[] {
if (data.length <= targetPoints) return data;
const step = Math.floor(data.length / targetPoints);
return data.filter((_, i) => i % step === 0);
}
const largeDataset = Array.from({ length: 10000 }, (_, i) => Math.sin(i / 100));
const downsampled = downsample(largeDataset, 200);
ui.lineChart({
id: "downsampled",
width: 60,
height: 20,
series: [{ data: downsampled, color: "#3b82f6" }],
});
See Also