# Portfolio echarts area chart

> Portfolio comparison card with hover-reveal, on the ECharts area chart

A shadcn/ui block from the [@evilcharts](https://evilcharts.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/evilcharts/portfolio-echarts-area-chart).

- Page, with a live preview: https://shadcn.exchange/r/evilcharts/portfolio-echarts-area-chart
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/evilcharts/portfolio-echarts-area-chart-light-25361ac834cef231.png
- Registry item: https://evilcharts.com/r/portfolio-echarts-area-chart.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://evilcharts.com/r/portfolio-echarts-area-chart.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: `echarts`, `motion`
- Registry items: `@evilcharts/echarts-area-chart`

## Files

### `src/registry/blocks/echarts/b-portfolio-echarts-area-chart.tsx`

```tsx
"use client";

import { EChartsAreaChart, type ChartConfig } from "@/registry/charts/echarts-area-chart";

const SERIES = [
  { key: "robinhood", label: "Robinhood", color: "#c3f000", pct: -4.41, delta: -2377.66 },
  { key: "coinbase", label: "Coinbase", color: "#2f6bff", pct: 1.15, delta: 617.22 },
] as const;

const chartData = [
  { date: "Dec 22", robinhood: 53916, coinbase: 53670 },
  { date: "Dec 23", robinhood: 54380, coinbase: 53080 },
  { date: "Dec 24", robinhood: 54760, coinbase: 52460 },
  { date: "Dec 25", robinhood: 54480, coinbase: 51880 },
  { date: "Dec 26", robinhood: 54060, coinbase: 51340 },
  { date: "Dec 27", robinhood: 53820, coinbase: 50900 },
  { date: "Dec 28", robinhood: 53520, coinbase: 50520 },
  { date: "Dec 29", robinhood: 53240, coinbase: 50200 },
  { date: "Dec 30", robinhood: 53080, coinbase: 49960 },
  { date: "Dec 31", robinhood: 52840, coinbase: 49760 },
  { date: "Jan 1", robinhood: 52700, coinbase: 49640 },
  { date: "Jan 2", robinhood: 52520, coinbase: 49600 },
  { date: "Jan 3", robinhood: 52420, coinbase: 49720 },
  { date: "Jan 4", robinhood: 52340, coinbase: 49980 },
  { date: "Jan 5", robinhood: 52240, coinbase: 50360 },
  { date: "Jan 6", robinhood: 52140, coinbase: 50820 },
  { date: "Jan 7", robinhood: 52080, coinbase: 51340 },
  { date: "Jan 8", robinhood: 52020, coinbase: 51900 },
  { date: "Jan 9", robinhood: 51960, coinbase: 52440 },
  { date: "Jan 10", robinhood: 51900, coinbase: 52960 },
  { date: "Jan 11", robinhood: 51860, coinbase: 53420 },
  { date: "Jan 12", robinhood: 51800, coinbase: 53780 },
  { date: "Jan 13", robinhood: 51740, coinbase: 54040 },
  { date: "Jan 14", robinhood: 51700, coinbase: 54200 },
  { date: "Jan 15", robinhood: 51640, coinbase: 54300 },
  { date: "Jan 16", robinhood: 51580, coinbase: 54320 },
  { date: "Jan 17", robinhood: 51538, coinbase: 54287 },
];

const chartConfig = {
  robinhood: { label: "Robinhood", colors: { light: ["#a6cc00"], dark: ["#c3f000"] } },
  coinbase: { label: "Coinbase", colors: { light: ["#2f6bff"], dark: ["#4c86ff"] } },
} satisfies ChartConfig;

const money = (value: number) =>
  Math.abs(value).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

export function EChartsPortfolioAreaChart() {
  return (
    <div className="flex h-full w-full flex-col pt-4">
      <div className="grid grid-cols-2 gap-x-8 px-4">
        {SERIES.map(({ key, label, color, pct, delta }) => (
          <div key={key} className="flex flex-col gap-1">
            <div className="text-muted-foreground flex items-center gap-2 text-sm">
              <span
                className="size-3 shrink-0 rounded-full border-2"
                style={{ borderColor: color }}
              />
              {label}
            </div>
            <div className="text-primary text-2xl font-semibold tracking-tight sm:text-3xl">
              {pct > 0 ? "+" : "−"}
              {Math.abs(pct).toFixed(2)}%
            </div>
            <div className={delta < 0 ? "text-rose-500" : "text-emerald-500"}>
              {delta < 0 ? "−" : "+"}${money(delta)}
            </div>
          </div>
        ))}
      </div>

      <EChartsAreaChart
        data={chartData}
        config={chartConfig}
        xDataKey="date"
        className="mt-4 min-h-0 w-full flex-1"
        curveType="step"
        enableHoverReveal
        chartOptions={{
          grid: { left: 0, right: 0, top: 16, bottom: 0 },
          yAxis: { type: "value", show: false, scale: true, boundaryGap: ["12%", "16%"] },
        }}
      >
        <EChartsAreaChart.Tooltip variant="frosted-glass" />
        <EChartsAreaChart.Area dataKey="robinhood" variant="dotted" strokeVariant="solid">
          <EChartsAreaChart.ActiveDot variant="ping" />
        </EChartsAreaChart.Area>
        <EChartsAreaChart.Area dataKey="coinbase" variant="dotted" strokeVariant="solid">
          <EChartsAreaChart.ActiveDot variant="ping" />
        </EChartsAreaChart.Area>
      </EChartsAreaChart>
    </div>
  );
}
```
