+14.2% Growth
45%
75%
50%
85%
60%
Weekly market trends
Track market trends and make informed decisions.
Installation
1. Install the following packages
npm
npm install motion2. Copy and paste the following code into your project
weekly-bars.tsx
1"use client";
2
3import { AnimatePresence, motion } from "motion/react";
4import { useEffect, useState } from "react";
5
6const Bar = ({ height, label, delay }: { height: number; label: string; delay: number }) => (
7 <div className="flex flex-col items-center gap-2 h-full justify-end group flex-1">
8 <motion.div
9 initial={{ height: 0, opacity: 0 }}
10 animate={{ height: `${height}%`, opacity: 1 }}
11 transition={{
12 duration: 0.5,
13 ease: "linear",
14 delay: delay * 0.1,
15 }}
16 className="w-8 relative bg-gray-200 dark:bg-gray-900 rounded-tl rounded-tr duration-300 cursor-pointer"
17 >
18 <div className="absolute -top-7 left-1/2 -translate-x-1/2">
19 <motion.span key={height} initial={{ opacity: 0, y: 5 }} animate={{ opacity: 1, y: 0 }} className="text-xs font-semibold text-gray-500 dark:text-white/70">
20 {Math.round(height)}%
21 </motion.span>
22 </div>
23 </motion.div>
24 <span className="text-[10px] font-semibold text-muted-foreground/60 uppercase tracking-widest mt-1">{label}</span>
25 </div>
26);
27
28const ChartAnimation = () => {
29 const [data, setData] = useState([45, 75, 50, 85, 60]);
30
31 useEffect(() => {
32 const interval = setInterval(() => {
33 setData(data.map(() => 35 + Math.random() * 60));
34 }, 4000);
35 return () => clearInterval(interval);
36 }, [data]);
37
38 const labels = ["Mon", "Tue", "Wed", "Thu", "Fri"];
39
40 return (
41 <div className="relative size-full pt-12 px-2 flex items-end justify-between gap-3 h-[180px]">
42 {/* Grid Lines */}
43 <div className="absolute inset-0 flex flex-col justify-between px-1 pointer-events-none">
44 {[...Array(5)].map((_, i) => (
45 <div key={i} className="w-full border-t border-black/5 dark:border-white/5" />
46 ))}
47 </div>
48
49 {/* Insight Popup */}
50 <AnimatePresence>
51 <motion.div
52 initial={{ opacity: 0, y: 20, scale: 0.9 }}
53 animate={{
54 opacity: 1,
55 y: 0,
56 scale: 1,
57 }}
58 transition={{
59 duration: 0.3,
60 }}
61 className="absolute bottom-[95%] right-0 px-2 py-1 rounded bg-gray-50 dark:bg-blue-950/40 border flex items-center gap-2"
62 >
63 <svg xmlns="http://www.w3.org/2000/svg" className="size-4 text-blue-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
64 <polyline points="22 7 13.5 15.5 8.5 10.5 2 17"></polyline>
65 <polyline points="16 7 22 7 22 13"></polyline>
66 </svg>
67 <span className="text-xs font-medium text-muted-foreground">+14.2% Growth</span>
68 </motion.div>
69 </AnimatePresence>
70
71 {/* Bars */}
72 {data.map((height, i) => (
73 <Bar key={i} height={height} label={labels[i]} delay={i} />
74 ))}
75 </div>
76 );
77};
78
79export function WeeklyBars() {
80 return (
81 <motion.div
82 className="bg-white/50 dark:bg-black/40 rounded-md p-8 border border-gray-200/50 dark:border-white/10 min-h-[300px] flex flex-col shadow-[inset_-12px_-8px_40px_#46464620] max-w-[400px]"
83 initial={{ opacity: 0, y: 30 }}
84 whileInView={{ opacity: 1, y: 0 }}
85 transition={{ duration: 0.4, ease: "circOut" }}
86 >
87 <div className="flex-1">
88 <ChartAnimation />
89 </div>
90 <div className="mt-6 flex flex-col">
91 <h3 className="font-semibold text-lg text-black dark:text-white">Weekly market trends</h3>
92 <p className="text-muted-foreground text-sm">Track market trends and make informed decisions.</p>
93 </div>
94 </motion.div>
95 );
96}
97
98export default WeeklyBars;
99