Weekly Bars

A dynamic weekly bar chart with smooth animations and growth insights.

Animation
Chart
Bar Chart
Weekly
UI
+14.2% Growth
45%
Mon
75%
Tue
50%
Wed
85%
Thu
60%
Fri

Weekly market trends

Track market trends and make informed decisions.


Installation

1. Install the following packages

npm
npm install motion

2. 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