The AreaChart component is a powerful addition to the Vue charts library, visualizing time series or categorical data as filled line charts. Examples ↗
<script lang="ts" setup>
defineOptions({
tags: ["areacharts", "multiplelines"],
});
withDefaults(
defineProps<{
showTitle?: boolean;
}>(),
{
showTitle: false,
},
);
const { height } = useResponsiveHeight({
default: 200,
sm: 300,
});
const colorMode = useColorMode();
interface AreaChartItem {
date: string;
desktop: number;
mobile: number;
}
const categories: ComputedRef<Record<string, BulletLegendItemInterface>> =
computed(() => ({
desktop: {
name: "Desktop",
color: "#3b82f6",
},
mobile: {
name: "Mobile",
color: "#22c55e",
},
}));
const AreaChartData: AreaChartItem[] = [
{ date: "2024-04-01", desktop: 75, mobile: 50 },
{ date: "2024-04-02", desktop: 125, mobile: 100 },
{ date: "2024-04-03", desktop: 167, mobile: 120 },
{ date: "2024-04-04", desktop: 260, mobile: 240 },
{ date: "2024-04-05", desktop: 240, mobile: 290 },
];
const xFormatter = (tick: number): string => {
return `${AreaChartData[tick]?.date}`;
};
</script>
<template>
<div
class="mx-auto max-w-3xl space-y-6 rounded-lg"
:class="showTitle ? 'p-6' : ''"
>
<div v-if="showTitle" class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Area Chart</h3>
<NuxtLink to="/blocks/area-charts">
<UButton
icon="i-lucide-copy"
size="sm"
variant="soft"
color="neutral"
/>
</NuxtLink>
</div>
<AreaChart
:key="colorMode.value"
:data="AreaChartData"
:height="height"
:categories="categories"
:y-grid-line="true"
:x-formatter="xFormatter"
:curve-type="CurveType.MonotoneX"
:legend-position="LegendPosition.TopRight"
:hide-legend="false"
/>
</div>
</template>
Compare every dither option—bayer, noise, and fade—on the same SaaS revenue series. Dither composes with gradientStops, while ditherTile controls the pattern scale.
<script lang="ts" setup>
defineOptions({
tags: ["areacharts", "singleline"],
});
import { useResponsiveHeight } from "~/composables/useResponsiveHeight";
withDefaults(
defineProps<{
showTitle?: boolean;
dither?: "bayer" | "noise" | "fade";
}>(),
{
showTitle: false,
dither: "bayer",
},
);
const categories: Record<string, BulletLegendItemInterface> = {
mrr: { name: "MRR", color: "#8b5cf6" },
};
const monthlyRevenue = [
{ month: "Jan", mrr: 18400 },
{ month: "Feb", mrr: 22100 },
{ month: "Mar", mrr: 26800 },
{ month: "Apr", mrr: 31700 },
{ month: "May", mrr: 38600 },
{ month: "Jun", mrr: 45200 },
{ month: "Jul", mrr: 53900 },
{ month: "Aug", mrr: 62400 },
];
const xFormatter = (tick: number): string => monthlyRevenue[tick]?.month ?? "";
const yFormatter = (value: number): string => `$${Math.round(value / 1000)}k`;
const { height } = useResponsiveHeight({
default: 170,
sm: 190,
});
</script>
<template>
<div
class="mx-auto max-w-4xl space-y-4 rounded-lg"
:class="showTitle ? 'p-6' : ''"
>
<div v-if="showTitle" class="flex items-center justify-between">
<div>
<p class="text-xs font-medium uppercase tracking-wider text-muted">
Revenue analytics
</p>
<h3 class="text-lg font-semibold text-highlighted">
Monthly recurring revenue
</h3>
</div>
<NuxtLink to="/blocks/area-charts">
<UButton
icon="i-lucide-copy"
size="sm"
variant="soft"
color="neutral"
/>
</NuxtLink>
</div>
<div class="rounded-xl bg-default p-4 ring ring-default">
<div class="mb-2 flex items-start justify-between gap-3">
<div>
<p class="text-sm font-semibold text-highlighted">
Monthly recurring revenue
</p>
<p class="text-xs text-muted">$18.4k → $62.4k in eight months</p>
</div>
<span
class="rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary"
>
+239%
</span>
</div>
<AreaChart
:data="monthlyRevenue"
:height="height"
:categories="categories"
:dither="dither"
:dither-tile="10"
:gradient-stops="[
{ offset: '0%', stopOpacity: 0.9 },
{ offset: '55%', stopOpacity: 0.3 },
{ offset: '100%', stopOpacity: 0 },
]"
:y-num-ticks="3"
:x-num-ticks="4"
:y-grid-line="true"
:hide-legend="true"
:x-formatter="xFormatter"
:y-formatter="yFormatter"
:line-width="2"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { useResponsiveHeight } from "~/composables/useResponsiveHeight";
defineOptions({
tags: ["areacharts", "basic"],
});
withDefaults(
defineProps<{
showTitle?: boolean;
}>(),
{
showTitle: false,
},
);
interface AreaChartItem {
month: string;
desktop: number;
}
const categories: Record<string, BulletLegendItemInterface> = {
desktop: { name: "Desktop", color: "#3b82f6" },
};
const AreaChartData: AreaChartItem[] = [
{ month: "January", desktop: 186 },
{ month: "February", desktop: 305 },
{ month: "March", desktop: 237 },
{ month: "April", desktop: 73 },
{ month: "May", desktop: 209 },
{ month: "June", desktop: 214 },
];
const xFormatter = (tick: number, i?: number, ticks?: number[]): string => {
if (typeof tick === "number" && AreaChartData[tick]?.month) {
return AreaChartData[tick].month;
}
return String(tick);
};
const { height } = useResponsiveHeight({
default: 200,
sm: 300,
});
</script>
<template>
<div
class="mx-auto max-w-3xl space-y-6 rounded-lg"
:class="showTitle ? 'p-6' : ''"
>
<div v-if="showTitle" class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Area Chart</h3>
<NuxtLink to="/blocks/area-charts">
<UButton
icon="i-lucide-copy"
size="sm"
variant="soft"
color="neutral"
/>
</NuxtLink>
</div>
<AreaChart
:data="AreaChartData"
:height="height"
y-label="Value"
x-label="Month"
:categories="categories"
:y-num-ticks="4"
:x-num-ticks="7"
:y-grid-line="true"
:legend-position="LegendPosition.TopRight"
:hide-legend="false"
:marker-config="{
desktop: {
type: 'circle',
size: 6,
strokeWidth: 2,
color: '#3b82f6',
},
}"
:x-formatter="xFormatter"
/>
</div>
</template>
<style scoped>
/* Stroke maps to color key in categories */
/* The color should match the color defined in categories */
.markers:deep(*[stroke="#3b82f6"]) {
marker: url("#circle-marker-desktop");
}
</style>
<script lang="ts" setup>
defineOptions({
tags: ["areacharts", "step"],
});
const { height } = useResponsiveHeight({
default: 200,
sm: 300,
});
interface AreaChartItem {
month: string;
desktop: number;
}
const AreaChartData: AreaChartItem[] = [
{ month: "January", desktop: 186 },
{ month: "February", desktop: 305 },
{ month: "March", desktop: 237 },
{ month: "April", desktop: 73 },
{ month: "May", desktop: 209 },
{ month: "June", desktop: 214 },
];
const categories: Record<string, BulletLegendItemInterface> = {
desktop: { name: "Desktop", color: "#3b82f6" },
};
const xFormatter = (tick: number, _i?: number, _ticks?: number[]): string => {
const month = AreaChartData[tick]?.month;
return month ? String(month) : "";
};
</script>
<template>
<div class="mx-auto max-w-3xl space-y-6 rounded-lg">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Area Chart</h3>
<NuxtLink to="/blocks/area-charts">
<UButton
icon="i-lucide-copy"
size="sm"
variant="soft"
color="neutral"
/>
</NuxtLink>
</div>
<AreaChart
:data="AreaChartData"
:height="height"
x-label="Month"
y-label="Score"
:categories="categories"
:y-num-ticks="4"
:x-num-ticks="7"
:y-grid-line="true"
:legend-position="LegendPosition.TopRight"
:hide-legend="false"
:x-formatter="xFormatter"
:curve-type="CurveType.Step"
/>
</div>
</template>
To create stacked area charts, simply include multiple data series in your categories and set the stacked prop to true. This approach makes it easy to visualize cumulative data trends in Vue and Nuxt applications:
<script lang="ts" setup>
defineOptions({
tags: ["areacharts", "stacked"],
});
const colorMode = useColorMode();
interface StackedAreaItem {
date: string;
saas: number;
marketplace: number;
services: number;
}
const categories: ComputedRef<Record<string, BulletLegendItemInterface>> =
computed(() => ({
saas: {
name: "SaaS",
color: "#3b82f6",
},
marketplace: {
name: "Marketplace",
color: "#22c55e",
},
services: {
name: "Services",
color: "#f59e0b",
},
}));
const stackedData: StackedAreaItem[] = [
{ date: "Jan", saas: 4000, marketplace: 2400, services: 2400 },
{ date: "Feb", saas: 3000, marketplace: 1398, services: 2210 },
{ date: "Mar", saas: 2000, marketplace: 9800, services: 2290 },
{ date: "Apr", saas: 2780, marketplace: 3908, services: 2000 },
{ date: "May", saas: 1890, marketplace: 4800, services: 2181 },
{ date: "Jun", saas: 2390, marketplace: 3800, services: 2500 },
{ date: "Jul", saas: 3490, marketplace: 4300, services: 2100 },
];
const { height } = useResponsiveHeight({
default: 250,
sm: 350,
});
const xFormatter = (i: number): string => `${stackedData[i]?.date}`;
const yFormatter = (value: number): string => `$${value.toLocaleString()}`;
</script>
<template>
<div class="mx-auto max-w-3xl space-y-6 rounded-lg">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Area Chart</h3>
<NuxtLink to="/blocks/area-charts">
<UButton
icon="i-lucide-copy"
size="sm"
variant="soft"
color="neutral"
/>
</NuxtLink>
</div>
<AreaChart
:key="colorMode.value"
:data="stackedData"
:height="height"
:categories="categories"
:stacked="true"
:x-formatter="xFormatter"
:y-formatter="yFormatter"
:curve-type="CurveType.MonotoneX"
:legend-position="LegendPosition.TopRight"
:hide-legend="false"
:y-grid-line="true"
:x-grid-line="false"
/>
</div>
</template>
| Prop | Type | Default | Description |
|---|---|---|---|
data | T[] | Required | Array of data points for the chart. Each element represents a data point. |
height | number | Required | Height of the chart in pixels. |
xLabel | string | undefined | Optional label for the x-axis. |
yLabel | string | undefined | Optional label for the y-axis. |
padding | { top: number; right: number; bottom: number; left: number; } | undefined | Optional padding for the chart (top, right, bottom, left). |
categories | Record<string, BulletLegendItemInterface> | Required | Series configuration: name and color for each data key. |
markerConfig | Record<string, MarkerConfig> | {} | Marker configuration for each series. |
xFormatter | axisFormatter | undefined | Formats X-axis labels. (tick, i, ticks) => string where tick can be a number or Date. |
yFormatter | axisFormatter | undefined | Formats Y-axis labels. (tick, i, ticks) => string where tick can be a number or Date. |
curveType | CurveType | undefined | Type of curve interpolation (see Curve Types section). |
hideArea | boolean | false | If true, hides the area fill and shows only the line. |
gradient | boolean | true | Fades the area fill toward the baseline. |
stacked | boolean | false | If true, the area chart will be stacked. |
gradientStops | Array<{ offset: string; stopOpacity: number }> | undefined | Custom gradient stops for the area fill. |
dither | boolean | 'bayer' | 'noise' | 'fade' | false | Applies a halftone texture to the area fill. |
ditherTile | number | 8 | Tile size in pixels for the dither pattern. |
ditherWash | number | undefined | Controls the solid color wash beneath the dither dots. |
strokeGradient | StrokeGradientStop[] | undefined | Paints the area outline with a horizontal multicolor gradient. |
lineWidth | number | 2 | Width of the line in pixels. |
lineDashArray | number[][] | undefined | SVG stroke-dasharray for dashed lines. |
xNumTicks | number | undefined | Desired number of ticks on the x-axis. |
xExplicitTicks | (number | string | Date)[] | undefined | Force specific ticks on the x-axis. |
minMaxTicksOnly | boolean | false | If true, only show first and last ticks on the x-axis. |
yNumTicks | number | undefined | Desired number of ticks on the y-axis. |
hideLegend | boolean | false | If true, hides the chart legend. |
hideTooltip | boolean | false | If true, hides the chart tooltip. |
legendPosition | LegendPosition | undefined | Position of the legend (see LegendPosition). |
legendStyle | string | Record<string, string> | undefined | Custom CSS style for the legend container. |
xDomainLine | boolean | false | Show domain (axis) line on the x-axis. |
yDomainLine | boolean | false | Show domain (axis) line on the y-axis. |
xTickLine | boolean | false | Show tick lines on the x-axis. |
yTickLine | boolean | false | Show tick lines on the y-axis. |
xGridLine | boolean | false | Show grid lines on the x-axis. |
yGridLine | boolean | false | Show grid lines on the y-axis. |
hideXAxis | boolean | false | If true, hides the x-axis. |
hideYAxis | boolean | false | If true, hides the y-axis. |
crosshairConfig | CrosshairConfig | undefined | Crosshair configuration for customizing the crosshair line. |
xAxisConfig | AxisConfig | undefined | Axis configuration for customizing the appearance of the x-axis. |
yAxisConfig | AxisConfig | undefined | Axis configuration for customizing the appearance of the y-axis. |
yDomain | [number | undefined, number | undefined] | undefined | Domain for the y-axis. |
xDomain | [number | undefined, number | undefined] | undefined | Domain for the x-axis. |
yExplicitTicks | (number | string | Date)[] | undefined | Force specific ticks on the y-axis. |
xMinMaxTicksOnly | boolean | false | If true, only show first and last ticks on the x-axis. |
yMinMaxTicksOnly | boolean | false | If true, only show first and last ticks on the y-axis. |
minMaxTicksOnlyShowGridLines | boolean | false | Show grid lines for min and max axis ticks. |
xMinMaxTicksOnlyShowGridLines | boolean | false | Show grid lines for min and max x-axis ticks. |
yMinMaxTicksOnlyShowGridLines | boolean | false | Show grid lines for min and max y-axis ticks. |
tooltipTitleFormatter | (data: T) => string | number | undefined | Custom formatter for tooltip titles. |
tooltip | TooltipConfig | undefined | Tooltip configuration (hideDelay, showDelay, followCursor). |
duration | number | undefined | Animation duration in milliseconds. |
stacked | boolean | false | If true, creates a stacked area chart where areas stack on top of each other. |
The data should be an array of objects where each object represents a data point:
interface AreaChartData {
[key: string]: string | number;
}
Categories define the visual appearance and metadata for each area:
interface AreaCategory {
name: string;
color: string;
}
interface AreaCategories {
[key: string]: AreaCategory;
}
Available curve types for area interpolation:
linear - Straight lines between pointslinearClosed - Closed straight linesbasis - B-spline curvesbasisClosed - Closed B-spline curvesbasisOpen - Open B-spline curvesbundle - Bundle spline curvescardinal - Cardinal spline curvescardinalClosed - Closed cardinal spline curvescardinalOpen - Open cardinal spline curvescatmullRom - Catmull-Rom spline curvescatmullRomClosed - Closed Catmull-Rom spline curvescatmullRomOpen - Open Catmull-Rom spline curvesmonotoneX - Monotone cubic interpolation (X axis)monotoneY - Monotone cubic interpolation (Y axis)natural - Natural cubic splinestep - Step functionstepBefore - Step function (step before)stepAfter - Step function (step after)