# Area Gradient

> A gradient area chart demonstrating desktop and mobile visitors over 6 months built with TanStack Charts.

A shadcn/ui block from the [@paceui](https://paceui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/paceui/tanstack-charts-area-gradient).

- Page, with a live preview: https://shadcn.exchange/r/paceui/tanstack-charts-area-gradient
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/paceui/tanstack-charts-area-gradient-light-7445059f5aa6fbfe.png
- Registry item: https://paceui.com/r/tanstack-charts-area-gradient.json
- Listed: 2026-10-21, source last changed 2026-10-21

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/paceui/tanstack-charts-area-gradient.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `@tanstack/charts`, `@tanstack/react-charts`, `d3-array`, `d3-scale`, `d3-shape`
- Registry items: `card`

## Files

### `components/tanstack-charts/area/area-gradient.tsx`

```tsx
import { areaY, d3Curve, defineChart, lineY } from "@tanstack/charts";
import { motion } from "@tanstack/charts/motion";
import { tooltip } from "@tanstack/charts/tooltip";
import { Chart } from "@tanstack/react-charts/core";
import { useMemo } from "react";

import { max } from "d3-array";
import { scaleLinear, scalePoint } from "d3-scale";
import { curveNatural } from "d3-shape";

import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";

const motionRenderer = motion({
    initial: "always",
    transition: { type: "spring", stiffness: 170, damping: 18, mass: 1 },
});

const chartData = [
    { month: "January", desktop: 186, mobile: 80 },
    { month: "February", desktop: 305, mobile: 200 },
    { month: "March", desktop: 237, mobile: 120 },
    { month: "April", desktop: 73, mobile: 190 },
    { month: "May", desktop: 209, mobile: 130 },
    { month: "June", desktop: 214, mobile: 140 },
].map((item) => ({
    ...item,
    stackedMobile: item.mobile,
    stackedDesktop: item.mobile + item.desktop,
}));

export function AreaGradient() {
    const definition = useMemo(() => {
        const yMax = max(chartData, (d) => d.stackedDesktop) ?? 0;

        return defineChart({
            renderer: motionRenderer,
            motion: {
                transition: { type: "spring", stiffness: 170, damping: 18, mass: 1 },
            },
            focus: "group-x",
            gradients: [
                {
                    id: "fillDesktop",
                    x1: 0,
                    y1: 0,
                    x2: 0,
                    y2: 1,
                    stops: [
                        { offset: 0.05, color: "var(--chart-1)", opacity: 0.8 },
                        { offset: 0.95, color: "var(--chart-1)", opacity: 0.1 },
                    ],
                },
                {
                    id: "fillMobile",
                    x1: 0,
                    y1: 0,
                    x2: 0,
                    y2: 1,
                    stops: [
                        { offset: 0.05, color: "var(--chart-2)", opacity: 0.8 },
                        { offset: 0.95, color: "var(--chart-2)", opacity: 0.1 },
                    ],
                },
            ],
            tooltip: {
                use: tooltip,
                motion: { type: "spring", stiffness: 170, damping: 18 },
                className: "font-sans! shadow-none! capitalize!",
                content: (points) => {
                    const datum = points[0]?.datum as (typeof chartData)[number];
                    if (!datum) return { rows: [] };
                    return {
                        title: String(points[0].xValue),
                        rows: [
                            {
                                label: "Desktop",
                                value: String(datum.desktop),
                                color: "var(--chart-1)",
                            },
                            {
                                label: "Mobile",
                                value: String(datum.mobile),
                                color: "var(--chart-2)",
                            },
                        ],
                    };
                },
            },
            marks: [
                areaY(chartData, {
                    id: "mobile",
                    x: (d) => d.month.slice(0, 3),
                    y: (d) => d.stackedMobile,
                    fill: "url(#fillMobile)",
                    fillOpacity: 0.4,
                    curve: d3Curve(curveNatural),
                }),
                lineY(chartData, {
                    id: "mobile-line",
                    x: (d) => d.month.slice(0, 3),
                    y: (d) => d.stackedMobile,
                    stroke: "var(--chart-2)",
                    strokeWidth: 2,
                    curve: d3Curve(curveNatural),
                    points: false,
                }),
                areaY(chartData, {
                    id: "desktop",
                    x: (d) => d.month.slice(0, 3),
                    y: (d) => d.stackedDesktop,
                    fill: "url(#fillDesktop)",
                    fillOpacity: 0.4,
                    curve: d3Curve(curveNatural),
                }),
                lineY(chartData, {
                    id: "desktop-line",
                    x: (d) => d.month.slice(0, 3),
                    y: (d) => d.stackedDesktop,
                    stroke: "var(--chart-1)",
                    strokeWidth: 2,
                    curve: d3Curve(curveNatural),
                    points: false,
                }),
            ],
            scales: {
                x: {
                    scale: scalePoint().domain(chartData.map((d) => d.month.slice(0, 3))),
                },
                y: {
                    scale: scaleLinear().domain([0, yMax]).nice(),
                    grid: true,
                },
            },
        });
    }, []);

    return (
        <Card className="gap-2">
            <CardHeader>
                <CardTitle className="text-lg">Network Ingress Throughput</CardTitle>
                <CardDescription>Real-time bandwidth consumption across primary data centers</CardDescription>
            </CardHeader>
            <CardContent>
                <Chart
                    definition={definition}
                    renderer={motionRenderer}
                    height={250}
                    ariaLabel="Gradient area chart demonstrating desktop and mobile visitors over 6 months"
                />
            </CardContent>
        </Card>
    );
}
```
