Skip to content

@vibe-labs/design-components-charts

Lightweight CSS-driven chart components for simple visualizations that don't need D3. For data-dense interactive charting, see @vibe-labs/design-components-graphs.

Installation

bash
npm install @vibe-labs/design-components-charts
css
@import "@vibe-labs/design-components-charts";
ts
import type { ChartHeatmapStyleProps } from "@vibe-labs/design-components-charts/types";

Contents

Tokens

CSS custom properties defined in @layer vibe.tokens (file: charts.css).

TokenDefaultDescription
--chart-border-radiusvar(--radius-md)Shared container radius
--chart-bgvar(--surface-base)Shared container background
--chart-paddingvar(--space-4)Shared container padding
--chart-heatmap-gap-sm1pxCell gap — small
--chart-heatmap-gap-md2pxCell gap — medium
--chart-heatmap-gap-lg3pxCell gap — large
--chart-heatmap-cell-radiusvar(--radius-sm)Cell border-radius (when data-rounded)
--chart-heatmap-cell-size-sm1remCell size — small
--chart-heatmap-cell-size-md1.5remCell size — medium
--chart-heatmap-cell-size-lg2remCell size — large
--chart-heatmap-intensity-0var(--surface-subtle)Empty / zero intensity
--chart-heatmap-intensity-125% accent mixLow intensity
--chart-heatmap-intensity-250% accent mixMedium intensity
--chart-heatmap-intensity-375% accent mixHigh intensity
--chart-heatmap-intensity-4var(--color-accent)Max intensity
--chart-legend-gapvar(--space-3)Legend item spacing
--chart-legend-swatch-size0.75remLegend color swatch size
--chart-legend-swatch-radiusvar(--radius-sm)Legend swatch radius

Generated Styles

Component classes generated into @layer vibe.components (file: charts.g.css).

Shared

.chart — container with border-radius, background, and padding.

Heatmap

ElementDescription
.chart-heatmapCSS Grid container
.chart-heatmap-cellIndividual cell
.chart-heatmap-label-xColumn header label
.chart-heatmap-label-yRow header label

Sizes (data-size): sm · md (default) · lg

Color scales (data-color-scale): accent (default) · success · warning · danger · info

Intensity (data-intensity on cells): 0 (empty) · 1 (low) · 2 (medium) · 3 (high) · 4 (max)

Flags:

FlagElementDescription
data-rounded.chart-heatmapApplies border-radius to cells
data-gap.chart-heatmapRemoves gap between cells
data-interactive.chart-heatmap-cellHover/focus states on individual cells

Note: Column count is set via inline grid-template-columns on .chart-heatmap, since it varies per dataset.

Legend

ElementDescription
.chart-legendFlex container for legend items
.chart-legend[data-layout="vertical"]Vertical legend layout
.chart-legend-itemSingle legend entry (swatch + label)
.chart-legend-swatchColor indicator square
.chart-legend-gradientGradient bar legend (min → max)
.chart-legend-gradient-barThe gradient bar itself

TypeScript Types

ts
export const ChartTypes = ["heatmap"] as const;
export type ChartType = (typeof ChartTypes)[number];

export const HeatmapIntensities = [0, 1, 2, 3, 4] as const;
export type HeatmapIntensity = (typeof HeatmapIntensities)[number];

export const HeatmapSizes = ["sm", "md", "lg"] as const;
export type HeatmapSize = (typeof HeatmapSizes)[number];

export const HeatmapColorScales = ["accent", "success", "warning", "danger", "info"] as const;
export type HeatmapColorScale = (typeof HeatmapColorScales)[number];

export interface ChartStyleProps {
  type?: ChartType;
}
export interface ChartHeatmapStyleProps {
  size?: HeatmapSize;
  colorScale?: HeatmapColorScale;
  rounded?: boolean;
  gap?: boolean;
}
export interface ChartHeatmapCellStyleProps {
  intensity?: HeatmapIntensity;
  interactive?: boolean;
}
export interface ChartLegendStyleProps {
  layout?: ChartLegendLayout;
}

Dist Structure

FileDescription
index.cssBarrel
charts.cssToken definitions
charts.g.cssGenerated component CSS
index.jsTypeScript runtime exports
index.d.tsTypeScript declarations

Dependencies

Runtime CSS token dependencies (not npm deps):

  • --surface-subtle, --surface-base from @vibe-labs/design-surfaces
  • --color-accent, --color-success, --color-warning, --color-danger, --color-info from @vibe-labs/design-colors
  • --radius-sm, --radius-md, --radius-full from @vibe-labs/design-borders
  • --space-* from @vibe-labs/design-spacing
  • --text-xs, --text-muted, --text-secondary from @vibe-labs/design-typography
  • --duration-fast, --ease-default from @vibe-labs/design-transitions
  • --border-default, --ring-color from @vibe-labs/design-borders / @vibe-labs/design-elevation

Build

bash
npm run build

Usage Guide

Import

css
@import "@vibe-labs/design-components-charts";
ts
import type { ChartHeatmapStyleProps } from "@vibe-labs/design-components-charts/types";

Variants

Heatmap size

Set data-size on .chart-heatmap: sm · md (default) · lg

Color scale

Set data-color-scale on .chart-heatmap: accent (default) · success · warning · danger · info

Cell intensity

Set data-intensity on each .chart-heatmap-cell: 0 (empty) · 1 (low) · 2 (medium) · 3 (high) · 4 (max)

Boolean flags

  • data-rounded on .chart-heatmap — applies border-radius to cells
  • data-gap on .chart-heatmap — removes gap between cells
  • data-interactive on .chart-heatmap-cell — adds hover/focus states to individual cells

Legend layout

Set data-layout on .chart-legend: omit for horizontal (default) · vertical

Examples

Heatmap — GitHub-style contribution grid

html
<!-- 7-column week-based heatmap with rounded cells -->
<div class="chart">
  <div class="chart-heatmap"
       data-size="md"
       data-color-scale="accent"
       data-rounded
       style="grid-template-columns: repeat(7, 1fr)">
    <!-- Each cell represents one day; intensity reflects activity -->
    <div class="chart-heatmap-cell" data-intensity="0"></div>
    <div class="chart-heatmap-cell" data-intensity="1"></div>
    <div class="chart-heatmap-cell" data-intensity="2"></div>
    <div class="chart-heatmap-cell" data-intensity="3"></div>
    <div class="chart-heatmap-cell" data-intensity="4"></div>
    <div class="chart-heatmap-cell" data-intensity="2"></div>
    <div class="chart-heatmap-cell" data-intensity="0"></div>
  </div>
</div>

Heatmap with interactive cells and labels

html
<!-- Heatmap with x/y labels and interactive hover on cells -->
<div class="chart">
  <div class="chart-heatmap"
       data-size="lg"
       data-color-scale="success"
       data-rounded
       style="grid-template-columns: repeat(5, 1fr)">
    <div class="chart-heatmap-label-x">Mon</div>
    <div class="chart-heatmap-label-x">Tue</div>
    <div class="chart-heatmap-label-x">Wed</div>
    <div class="chart-heatmap-label-x">Thu</div>
    <div class="chart-heatmap-label-x">Fri</div>

    <div class="chart-heatmap-cell" data-intensity="1" data-interactive></div>
    <div class="chart-heatmap-cell" data-intensity="3" data-interactive></div>
    <div class="chart-heatmap-cell" data-intensity="4" data-interactive></div>
    <div class="chart-heatmap-cell" data-intensity="2" data-interactive></div>
    <div class="chart-heatmap-cell" data-intensity="0" data-interactive></div>
  </div>
</div>

Categorical legend

html
<!-- Horizontal legend items with color swatches -->
<div class="chart-legend">
  <div class="chart-legend-item">
    <span class="chart-legend-swatch" style="background-color: var(--color-accent)"></span>
    <span>Series A</span>
  </div>
  <div class="chart-legend-item">
    <span class="chart-legend-swatch" style="background-color: var(--color-success)"></span>
    <span>Series B</span>
  </div>
</div>

Gradient legend (for heatmaps)

html
<!-- Min → Max gradient bar, typically placed below a heatmap -->
<div class="chart-legend-gradient">
  <span>Less</span>
  <div class="chart-legend-gradient-bar"></div>
  <span>More</span>
</div>

With Vue

Use @vibe-labs/design-vue-charts for <SbChart>, <SbChartHeatmap>, <SbChartHeatmapCell>, and <SbChartLegend> components that accept the typed props and handle data-attribute mapping automatically.

Vibe