Componentcharts0.86 KB gzipZero dependencies
Horizon Chart
Banded area chart for dense time series.
Preview
Live Preview
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add horizon-chartOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { HorizonChart } from "@/components/ui/horizon-chart";
<HorizonChart data={[4, 9, 6, 14]} />Usage guidance
Use Horizon Chart when a ticket stub surface needs Banded area chart for dense time series. Keep props minimal and prefer composition with sibling stubs.
Avoid Horizon Chart for long form flows or dense data grids where a dedicated layout block fits better.
Source code
horizon-chart.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export interface HorizonChartProps extends React.SVGAttributes<SVGSVGElement> {
data: number[];
bands?: number;
width?: number;
height?: number;
}
/** Horizon chart: dense time series folded into stacked translucent bands. */
export function HorizonChart({
data,
bands = 3,
width = 280,
height = 64,
className,
...props
}: HorizonChartProps) {
const bandCount = Math.max(1, Math.floor(bands));
const n = data.length;
if (n === 0) {
return <svg width={width} height={height} className={className} aria-hidden="true" {...props} />;
}
const max = Math.max(...data, 1);
const x = (i: number) => (i / Math.max(n - 1, 1)) * width;
const bandPath = (band: number): string => {
const floor = (max * band) / bandCount;
const span = max / bandCount || 1;
const top = data
.map((v, i) => {
const clipped = Math.min(Math.max(v - floor, 0), span);
const y = height - (clipped / span) * height;
return `${i === 0 ? "M" : "L"}${x(i).toFixed(2)},${y.toFixed(2)}`;
})
.join(" ");
return `${top} L${x(n - 1).toFixed(2)},${height} L${x(0).toFixed(2)},${height} Z`;
};
return (
<svg
width={width}
height={height}
viewBox={`0 0 ${width} ${height}`}
preserveAspectRatio="none"
role="img"
aria-label={`Horizon chart, ${n} points, peak ${max}`}
className={cn("text-accent", className)}
{...props}
>
<title>{`Horizon chart with ${n} points across ${bandCount} bands`}</title>
{Array.from({ length: bandCount }).map((_, b) => (
<path
key={b}
d={bandPath(b)}
fill="currentColor"
opacity={0.25 + (0.55 * (b + 1)) / bandCount}
/>
))}
</svg>
);
}
Props
| Prop | Type | Description |
|---|---|---|
| data | number[] | Series values (required). |
| bands | number | Band count (default 3). |
| width | number | SVG width (default 280). |
| height | number | SVG height (default 64). |