New

RevenueChart

CSS-only area chart with gradient fill, axis labels, and hover interaction

Dashboard & Analyticschartrevenuearea-chartanalytics

Dependencies

shadcn/ui components needed:

npx shadcn@latest add card

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client"
2
3import * as React from "react"
4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
5import { cn } from "@/lib/utils"
6
7interface RevenueChartProps {
8 data?: { label: string; value: number }[]
9 className?: string
10}
11
12export function RevenueChart({ data = [
13 { label: "Jan", value: 12000 },
14 { label: "Feb", value: 19000 },
15 { label: "Mar", value: 15000 },
16 { label: "Apr", value: 22000 },
17 { label: "May", value: 28000 },
18 { label: "Jun", value: 24000 },
19], className }: RevenueChartProps) {
20 const total = data.reduce((sum, d) => sum + d.value, 0)
21 const max = Math.max(...data.map(d => d.value))
22 const width = 600
23 const height = 200
24 const padding = 40
25
26 const points = data.map((d, i) => {
27 const x = padding + (i / (data.length - 1)) * (width - padding * 2)
28 const y = height - padding - (d.value / max) * (height - padding * 2)
29 return `${x},${y}`
30 }).join(" ")
31
32 const areaPoints = `${padding},${height - padding} ${points} ${width - padding},${height - padding}`
33
34 return (
35 <Card className={cn("w-full", className)}>
36 <CardHeader className="pb-4">
37 <CardTitle>Revenue</CardTitle>
38 <p className="text-2xl font-bold text-primary">${total.toLocaleString()}</p>
39 </CardHeader>
40 <CardContent>
41 <div className="relative w-full overflow-hidden">
42 <svg viewBox={`0 0 ${width} ${height}`} className="w-full h-auto">
43 <defs>
44 <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
45 <stop offset="0%" stopColor="rgb(59 130 246)" stopOpacity="0.4" />
46 <stop offset="100%" stopColor="rgb(59 130 246)" stopOpacity="0" />
47 </linearGradient>
48 </defs>
49 <polygon points={areaPoints} fill="url(#gradient)" />
50 <polyline points={points} fill="none" stroke="rgb(59 130 246)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
51 {data.map((d, i) => {
52 const x = padding + (i / (data.length - 1)) * (width - padding * 2)
53 const y = height - padding - (d.value / max) * (height - padding * 2)
54 return (
55 <g key={i} className="group">
56 <circle cx={x} cy={y} r="6" fill="white" stroke="rgb(59 130 246)" strokeWidth="3" className="group-hover:r-8 transition-all duration-200" />
57 <text x={x} y={height - 10} textAnchor="middle" className="text-xs fill-muted-foreground">{d.label}</text>
58 </g>
59 )
60 })}
61 {[0, 0.5, 1].map((p, i) => (
62 <g key={i}>
63 <line x1={padding - 10} y1={height - padding - p * (height - padding * 2)} x2={width - padding} y2={height - padding - p * (height - padding * 2)} stroke="rgb(226 232 240)" strokeDasharray="4" />
64 <text x={padding - 15} y={height - padding - p * (height - padding * 2) + 4} textAnchor="end" className="text-xs fill-muted-foreground">${(max * p / 1000).toFixed(0)}k</text>
65 </g>
66 ))}
67 </svg>
68 </div>
69 </CardContent>
70 </Card>
71 )
72}

Related Dashboard & Analytics Components

Command Palette

Search for a command to run...