Every item is $19. Or get all items for $259, paid once.

Get all items
mebius.design
mebius.design

Animated candlestick chart in React for a shadcn dashboard

shadcn/ui’s charts cover area, bar, line, pie, radar and radial charts, but not candlesticks. For a candlestick card in a shadcn dashboard, install a registry block: the free Ethereum Chart from mebius.design is a React + Tailwind OHLC card with volume bars, a period switch, keyboard inspection and anime.js motion, added with one shadcn CLI command. For a full trading screen, use a financial charting library instead.

6 min readUpdated Nov 8, 2026React + Tailwind

Pick the right tool first

A dashboard card and a trading terminal need different charts.

shadcn/ui’s chart components wrap Recharts and theme it with your CSS variables. Recharts has no candlestick series, so a candlestick there means drawing custom bar shapes for the bodies and wicks yourself. That leaves three routes:

  • A financial charting library such as TradingView’s Lightweight Charts (Apache 2.0, canvas). It is built for trading screens: thousands of candles, panning, zooming and live updates. It is not a React component and doesn’t use your Tailwind tokens.
  • Recharts with a custom shape: you stay in the shadcn stack and write the candle drawing, the axis and the tooltip yourself.
  • A finished candlestick card from a shadcn registry, which drops into a dashboard grid next to your other cards. This guide uses that route.

If your page is a price chart people trade from, take the library. If it is a card in a dashboard that shows how a coin, stock or fund moved this week, a card is less work and matches the rest of the page.


Install the chart with the shadcn CLI

React 19, Tailwind CSS v4 and shadcn CLI 4 or later.

The Ethereum Chart is one of the 20 items of the mebius.design open starter pack: its code is MIT and installs straight from its URL, with no account or token. The command also brings the charts theme it needs, which only adds tokens scoped to the chart cards (they carry a data-charts attribute), so it doesn’t change your app’s colours.

Terminal
npx shadcn@latest add https://www.mebius.design/r/charts-ethereum.json

The other free charts install the same way through the @mebius registry, with a free account and a personal access token from Settings › Tokens (the install guide has the setup).

The CLI writes components/ethereum-chart.tsx, the card parts it uses and anime.js. Render it with its sample week to check the setup:

app/page.tsx
import { EthereumChart } from "@/components/ethereum-chart"

export default function Page() {
  return <EthereumChart className="max-w-[600px]" />
}

Feed it your own candles

One period per segment of the Week / Month / Year switch.

A candle is { time, open, high, low, close, volume } with the time in milliseconds, oldest first. Each period gives the switch a segment and tells the x axis whether to name days, weeks or months. The example loads three periods from your own endpoint and hides the NAV and market price figures, which only make sense for a fund:

components/eth-price-card.tsx
"use client"

import * as React from "react"

import { EthereumChart, type EthereumCandle, type EthereumPeriod } from "@/components/ethereum-chart"

// Your API answers with rows of [time in ms, open, high, low, close, volume], oldest first.
type Row = [number, number, number, number, number, number]

const toCandles = (rows: Row[]): EthereumCandle[] =>
  rows.map(([time, open, high, low, close, volume]) => ({ time, open, high, low, close, volume }))

async function load(interval: "1d" | "1w", limit: number) {
  const response = await fetch(`/api/candles?symbol=ETH&interval=${interval}&limit=${limit}`)
  if (!response.ok) throw new Error(`Candles failed: ${response.status}`)
  return toCandles((await response.json()) as Row[])
}

export function EthPriceCard() {
  const [periods, setPeriods] = React.useState<EthereumPeriod[] | null>(null)

  React.useEffect(() => {
    let cancelled = false
    Promise.all([load("1d", 7), load("1d", 30), load("1w", 52)]).then(([week, month, year]) => {
      if (cancelled) return
      setPeriods([
        { value: "week", label: "W", name: "Week", candles: week, unit: "day" },
        { value: "month", label: "M", name: "Month", candles: month, unit: "week" },
        { value: "year", label: "Y", name: "Year", candles: year, unit: "month" },
      ])
    })
    return () => {
      cancelled = true
    }
  }, [])

  if (!periods) return <div className="h-[562px] max-w-[600px] rounded-2xl bg-neutral-100" />

  return <EthereumChart className="max-w-[600px]" title="Ethereum" symbol="ETH" periods={periods} stats={[]} />
}

The price in the header is the last close and the badge is the change from the first open, so both follow your data. Prices, axis labels and times are formatted with locale and currency (en-US and USD by default); formatTime replaces the axis and tooltip times, which are in UTC by default.


Put it in a dashboard grid

The card is as wide as its container; the height follows its content.

Every chart card from the same registry shares the theme, so a candlestick card sits next to a holdings card without extra styling. Here with the Your Asset Chart (install it the same way, @mebius/charts-your-asset):

app/dashboard/page.tsx
import { EthereumChart } from "@/components/ethereum-chart"
import { YourAssetChart } from "@/components/your-asset-chart"

export default function DashboardPage() {
  return (
    <main className="grid gap-4 p-6 xl:grid-cols-[minmax(0,600px)_minmax(0,1fr)]">
      <EthereumChart />
      <YourAssetChart />
    </main>
  )
}

Narrow screens

On a narrow card the period switch wraps under the price and the figures stack in one column, so the same card works in a phone layout.


Motion and accessibility

  • The plot is one slider: arrow keys move between candles, Page Up and Page Down jump a tenth of them, Home and End go to the first and last, Escape hides the tooltip. Screen readers hear the candle’s time and prices.
  • Candles grow out of their opens one after another, and a new period morphs the old candles into the new ones. With prefers-reduced-motion set to reduce nothing animates.
  • The server render is the final state, so the card shows real numbers before JavaScript runs.

Item pages, kits and guides this guide uses.