Flächendiagramm
Eine Linie mit ruhiger Fläche darunter, als Tönung, Verlauf oder gestapelte Bänder mit Lücke in Flächenfarbe.
Eine von 7 Components in Charts
Variants
Details
Was Flächendiagramm mitbringt, aus Registry und Quellcode gelesen.
- Kategorie
- Charts
- Bereich
- Elements
- Variants
- 3
- Version
- 1.0.0 · seit 1.0.0
- Datei
- components/ui/area-chart.tsx
- Bringt mit
- utilskitchart
- npm-Pakete
- Keine
- Sprachen
- Texte kommen über Props
- Studio
- Im Code anpassen
- Mit KI bauen
- Per MCP in Claude, Cursor, Copilot und Codex
Props
Die Schnittstelle AreaChartProps aus components/ui/area-chart.tsx. Beschreibungen stammen aus den Kommentaren im Code und sind auf Englisch. Nimmt außerdem alle Props von ChartA11y an.
dataPflichtDatum[]Rows, one per x value, e.g. { day: '2026-09-14', visits: 412 }
xKeyPflichtstringKey of the x value. "2026-03" and "2026-03-14" are read as dates and formatted per language.
seriesPflichtChartSeries[]One area per series, in slot order (accent, grey, two accent tones)
formatoptionalIntl.NumberFormatOptionsValue format, e.g. { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }
xFormatoptionalIntl.DateTimeFormatOptionstooltipXFormatoptionalIntl.DateTimeFormatOptionsstackedoptionalbooleanStack the series to a total. Each band gets a tint and a top line in its series color.
filloptional'wash' | 'gradient'wash: an even, quiet tint. gradient: the tint fades towards the baseline.
curveoptional'smooth' | 'linear'heightoptionalnumberPlot height in px, axis labels included
legendoptionalbooleanLegend above the plot. Default: for two series and more.
xLabeloptionalstringHeader of the first table column
Barrierefreiheit
Aus dem Quellcode der Component abgeleitet.
- Kommt ohne Client-State aus. Der Server schreibt sie vollständig, sie ist auch ohne JavaScript lesbar.
Bewegung
- Ohne Animationen, sie steht sofort ruhig da.
Quellcode
Die Datei, die aiw add in dein Projekt legt. Sie gehört danach dir.
Datei anzeigen, 134 Zeilen
'use client';
import { useId } from 'react';
import { CartesianFrame, GlideDot, linePath, seriesColor, seriesOpacity, type ChartA11y, type ChartSeries, type Datum } from '@/components/ui/chart';
export interface AreaChartProps extends ChartA11y {
/** Rows, one per x value, e.g. { day: '2026-09-14', visits: 412 } */
data: Datum[];
/** Key of the x value. "2026-03" and "2026-03-14" are read as dates and formatted per language. */
xKey: string;
/** One area per series, in slot order (accent, grey, two accent tones) */
series: ChartSeries[];
/** Value format, e.g. { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 } */
format?: Intl.NumberFormatOptions;
xFormat?: Intl.DateTimeFormatOptions;
tooltipXFormat?: Intl.DateTimeFormatOptions;
/** Stack the series to a total. Each band gets a tint and a top line in its series color. */
stacked?: boolean;
/** wash: an even, quiet tint. gradient: the tint fades towards the baseline. */
fill?: 'wash' | 'gradient';
curve?: 'smooth' | 'linear';
/** Plot height in px, axis labels included */
height?: number;
/** Legend above the plot. Default: for two series and more. */
legend?: boolean;
/** Header of the first table column */
xLabel?: string;
className?: string;
}
/**
* Areas over time: a single tinted area, a gradient, or stacked bands.
* <AreaChart data={rows} xKey="day" series={[{ key: 'visits', label: 'Visits' }]} fill="gradient" />
*/
export function AreaChart({ data, xKey, series, format, xFormat, tooltipXFormat, stacked = false, fill = 'wash', curve = 'smooth', height = 260, legend, xLabel, label, summary, labels, animate, className }: AreaChartProps) {
const uid = useId().replace(/[^a-zA-Z0-9]/g, '');
const num = (d: Datum, k: string) => (typeof d[k] === 'number' ? (d[k] as number) : null);
// Cumulative tops per series when stacked
const tops = series.map((_, si) => data.map((d) => series.slice(0, si + 1).reduce((a, s) => a + Math.max(0, num(d, s.key) ?? 0), 0)));
const all = stacked ? tops[tops.length - 1] ?? [] : data.flatMap((d) => series.map((s) => num(d, s.key))).filter((v): v is number => v !== null);
const extent: [number, number] = [Math.min(0, ...all), Math.max(0, ...all)];
const smooth = curve === 'smooth';
return (
<CartesianFrame
data={data}
xKey={xKey}
series={series}
format={format}
xFormat={xFormat}
tooltipXFormat={tooltipXFormat}
height={height}
scale="point"
extent={extent}
legend={legend}
legendShape={stacked ? 'rect' : 'line'}
crosshair
total={stacked}
xLabel={xLabel}
label={label}
summary={summary}
labels={labels}
animate={animate}
className={className}
marks={({ cat, val, animated, focus }) => (
<>
<defs>
{series.map((s, si) => (
<linearGradient key={s.key} id={`${uid}-g${si}`} x1="0" x2="0" y1="0" y2="1">
<stop offset="0" stopColor={seriesColor(si, s.color)} stopOpacity={stacked ? 0.55 : 0.3} />
<stop offset="1" stopColor={seriesColor(si, s.color)} stopOpacity={stacked ? 0.22 : 0} />
</linearGradient>
))}
</defs>
{/* Draw from the last series down, so the first sits in front when not stacked */}
{[...series.keys()].reverse().map((si) => {
const s = series[si];
const color = seriesColor(si, s.color);
const style = animated ? ({ '--kitch-d': `${si * 120}ms` } as React.CSSProperties) : undefined;
const op = seriesOpacity(si, focus);
if (stacked) {
const upper: [number, number][] = data.map((_, i) => [cat(i), val(tops[si][i])]);
const lower: [number, number][] = data.map((_, i) => [cat(i), val(si ? tops[si - 1][i] : 0)]).reverse() as [number, number][];
const top = linePath(upper, smooth);
const bottom = linePath(lower, smooth).replace(/^M/, 'L');
return (
<g key={s.key} className="kitch-series" opacity={op}>
<path d={`${top} ${bottom} Z`} fill={fill === 'gradient' ? `url(#${uid}-g${si})` : color} fillOpacity={fill === 'gradient' ? 1 : 0.4} className={animated ? 'kitch-clip' : undefined} style={style} />
{/* Each band ends in a crisp line of its own color */}
<path d={top} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" pathLength={1} className={animated ? 'kitch-draw' : undefined} style={style} />
</g>
);
}
const segments: [number, number][][] = [[]];
data.forEach((d, i) => {
const v = num(d, s.key);
if (v !== null) segments[segments.length - 1].push([cat(i), val(v)]);
else if (segments[segments.length - 1].length) segments.push([]);
});
return (
<g key={s.key} className="kitch-series" opacity={op}>
{segments
.filter((seg) => seg.length > 1)
.map((seg, k) => {
const top = linePath(seg, smooth);
const base = val(Math.max(extent[0], 0));
return (
<g key={k}>
<path
d={`${top} L${seg[seg.length - 1][0]} ${base} L${seg[0][0]} ${base} Z`}
fill={fill === 'gradient' ? `url(#${uid}-g${si})` : color}
fillOpacity={fill === 'gradient' ? 1 : si === 0 ? 0.12 : 0.1}
className={animated ? 'kitch-clip' : undefined}
style={style}
/>
<path d={top} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" strokeDasharray={s.dashed ? '4 5' : undefined} pathLength={s.dashed ? undefined : 1} className={animated ? (s.dashed ? 'kitch-clip' : 'kitch-draw') : undefined} style={style} />
</g>
);
})}
</g>
);
})}
</>
)}
overlay={({ cat, val, shown, open, jump, focus }) =>
shown !== null &&
series.map((s, si) => {
const v = stacked ? tops[si][shown] : num(data[shown], s.key);
return v !== null && v !== undefined ? <GlideDot key={s.key} x={cat(shown)} y={val(v)} open={open} jump={jump} color={seriesColor(si, s.color)} opacity={seriesOpacity(si, focus)} /> : null;
})
}
/>
);
}Häufige Fragen
Wie installiere ich Flächendiagramm?
Mit aiw add @ai-website/area-chart. Der Befehl legt die Datei components/ui/area-chart.tsx in dein Projekt, der Code gehört danach dir. Mit dabei sind chart. Weitere npm-Pakete braucht sie nicht.
Welche Varianten hat Flächendiagramm?
3 Varianten, Einfach, Verlauf und Gestapelt.
Kann ein KI-Assistent Flächendiagramm einbauen?
Ja. Über den MCP-Server der aiw CLI finden Claude, Cursor, GitHub Copilot, Windsurf, Codex und Gemini Flächendiagramm mit aiw_components und installieren sie mit aiw_add @ai-website/area-chart.