Appearance
@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-chartscss
@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).
| Token | Default | Description |
|---|---|---|
--chart-border-radius | var(--radius-md) | Shared container radius |
--chart-bg | var(--surface-base) | Shared container background |
--chart-padding | var(--space-4) | Shared container padding |
--chart-heatmap-gap-sm | 1px | Cell gap — small |
--chart-heatmap-gap-md | 2px | Cell gap — medium |
--chart-heatmap-gap-lg | 3px | Cell gap — large |
--chart-heatmap-cell-radius | var(--radius-sm) | Cell border-radius (when data-rounded) |
--chart-heatmap-cell-size-sm | 1rem | Cell size — small |
--chart-heatmap-cell-size-md | 1.5rem | Cell size — medium |
--chart-heatmap-cell-size-lg | 2rem | Cell size — large |
--chart-heatmap-intensity-0 | var(--surface-subtle) | Empty / zero intensity |
--chart-heatmap-intensity-1 | 25% accent mix | Low intensity |
--chart-heatmap-intensity-2 | 50% accent mix | Medium intensity |
--chart-heatmap-intensity-3 | 75% accent mix | High intensity |
--chart-heatmap-intensity-4 | var(--color-accent) | Max intensity |
--chart-legend-gap | var(--space-3) | Legend item spacing |
--chart-legend-swatch-size | 0.75rem | Legend color swatch size |
--chart-legend-swatch-radius | var(--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
| Element | Description |
|---|---|
.chart-heatmap | CSS Grid container |
.chart-heatmap-cell | Individual cell |
.chart-heatmap-label-x | Column header label |
.chart-heatmap-label-y | Row 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:
| Flag | Element | Description |
|---|---|---|
data-rounded | .chart-heatmap | Applies border-radius to cells |
data-gap | .chart-heatmap | Removes gap between cells |
data-interactive | .chart-heatmap-cell | Hover/focus states on individual cells |
Note: Column count is set via inline grid-template-columns on .chart-heatmap, since it varies per dataset.
Legend
| Element | Description |
|---|---|
.chart-legend | Flex container for legend items |
.chart-legend[data-layout="vertical"] | Vertical legend layout |
.chart-legend-item | Single legend entry (swatch + label) |
.chart-legend-swatch | Color indicator square |
.chart-legend-gradient | Gradient bar legend (min → max) |
.chart-legend-gradient-bar | The 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
| File | Description |
|---|---|
index.css | Barrel |
charts.css | Token definitions |
charts.g.css | Generated component CSS |
index.js | TypeScript runtime exports |
index.d.ts | TypeScript declarations |
Dependencies
Runtime CSS token dependencies (not npm deps):
--surface-subtle,--surface-basefrom@vibe-labs/design-surfaces--color-accent,--color-success,--color-warning,--color-danger,--color-infofrom@vibe-labs/design-colors--radius-sm,--radius-md,--radius-fullfrom@vibe-labs/design-borders--space-*from@vibe-labs/design-spacing--text-xs,--text-muted,--text-secondaryfrom@vibe-labs/design-typography--duration-fast,--ease-defaultfrom@vibe-labs/design-transitions--border-default,--ring-colorfrom@vibe-labs/design-borders/@vibe-labs/design-elevation
Build
bash
npm run buildUsage 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-roundedon.chart-heatmap— applies border-radius to cellsdata-gapon.chart-heatmap— removes gap between cellsdata-interactiveon.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.