1+ import { motion , useMotionValue , useTransform , useSpring } from 'framer-motion' ;
12import { BarChart3 , Users , Search , Zap , Shield , Globe } from 'lucide-react' ;
3+ import { useRef , useState } from 'react' ;
24
3- const Features = ( ) => {
4- const features = [
5- {
6- icon : BarChart3 ,
7- title : 'Activity Analytics' ,
8- description : 'Comprehensive charts and graphs showing commit patterns, contribution streaks, and repository activity over time.' ,
9- bgColor : 'bg-blue-100' ,
10- iconColor : 'text-blue-600' ,
11- hoverColor : 'hover:bg-blue-400/50 dark:hover:bg-blue-900/30' ,
12- borderColor : 'hover:border-blue-200 dark:hover:border-blue-700'
13- } ,
14- {
15- icon : Users ,
16- title : 'Multi-User Tracking' ,
17- description : 'Monitor multiple GitHub users simultaneously and compare their activity levels and contribution patterns.' ,
18- bgColor : 'bg-green-100' ,
19- iconColor : 'text-green-600' ,
20- hoverColor : 'hover:bg-green-400/50 dark:hover:bg-green-900/30' ,
21- borderColor : 'hover:border-green-200 dark:hover:border-green-700'
22- } ,
23- {
24- icon : Search ,
25- title : 'Smart Search' ,
26- description : 'Quickly find and add users to your tracking list with intelligent search and auto-suggestions.' ,
27- bgColor : 'bg-purple-100' ,
28- iconColor : 'text-purple-600' ,
29- hoverColor : 'hover:bg-purple-400/50 dark:hover:bg-purple-900/30' ,
30- borderColor : 'hover:border-purple-200 dark:hover:border-purple-700'
31- } ,
32- {
33- icon : Zap ,
34- title : 'Real-time Updates' ,
35- description : 'Get instant notifications and updates when tracked users make new contributions or repositories.' ,
36- bgColor : 'bg-orange-100' ,
37- iconColor : 'text-orange-600' ,
38- hoverColor : 'hover:bg-orange-400/50 dark:hover:bg-orange-900/30' ,
39- borderColor : 'hover:border-orange-200 dark:hover:border-orange-700'
40- } ,
41- {
42- icon : Shield ,
43- title : 'Privacy First' ,
44- description : 'All data is fetched from public GitHub APIs. We don\'t store personal information or require GitHub access.' ,
45- bgColor : 'bg-red-100' ,
46- iconColor : 'text-red-600' ,
47- hoverColor : 'hover:bg-red-400/50 dark:hover:bg-red-900/30' ,
48- borderColor : 'hover:border-red-200 dark:hover:border-red-700'
49- } ,
50- {
51- icon : Globe ,
52- title : 'Export & Share' ,
53- description : 'Export activity reports and share insights with your team through various formats and integrations.' ,
54- bgColor : 'bg-indigo-100' ,
55- iconColor : 'text-indigo-600' ,
56- hoverColor : 'hover:bg-indigo-400/50 dark:hover:bg-indigo-900/30' ,
57- borderColor : 'hover:border-indigo-200 dark:hover:border-indigo-700'
58- }
59- ] ;
5+ const features = [
6+ {
7+ icon : BarChart3 ,
8+ title : 'Activity Analytics' ,
9+ description : 'Comprehensive charts showing commit patterns, contribution streaks, and repository activity over time.' ,
10+ iconBg : 'bg-blue-500/15 dark:bg-blue-500/20' ,
11+ iconColor : 'text-blue-600 dark:text-blue-400' ,
12+ glow : '59,130,246' ,
13+ border : 'hover:border-blue-400/50 dark:hover:border-blue-500/50' ,
14+ } ,
15+ {
16+ icon : Users ,
17+ title : 'Multi-User Tracking' ,
18+ description : 'Monitor multiple GitHub users simultaneously and compare contribution patterns side by side.' ,
19+ iconBg : 'bg-emerald-500/15 dark:bg-emerald-500/20' ,
20+ iconColor : 'text-emerald-600 dark:text-emerald-400' ,
21+ glow : '16,185,129' ,
22+ border : 'hover:border-emerald-400/50 dark:hover:border-emerald-500/50' ,
23+ } ,
24+ {
25+ icon : Search ,
26+ title : 'Smart Search' ,
27+ description : 'Intelligent search with auto-suggestions to instantly find and add users to your dashboard.' ,
28+ iconBg : 'bg-violet-500/15 dark:bg-violet-500/20' ,
29+ iconColor : 'text-violet-600 dark:text-violet-400' ,
30+ glow : '139,92,246' ,
31+ border : 'hover:border-violet-400/50 dark:hover:border-violet-500/50' ,
32+ } ,
33+ {
34+ icon : Zap ,
35+ title : 'Real-time Updates' ,
36+ description : 'Instant notifications when tracked users push commits, open PRs, or create repositories.' ,
37+ iconBg : 'bg-amber-500/15 dark:bg-amber-500/20' ,
38+ iconColor : 'text-amber-600 dark:text-amber-400' ,
39+ glow : '245,158,11' ,
40+ border : 'hover:border-amber-400/50 dark:hover:border-amber-500/50' ,
41+ } ,
42+ {
43+ icon : Shield ,
44+ title : 'Privacy First' ,
45+ description : 'Public GitHub APIs only. Zero personal data stored, no authentication required from users.' ,
46+ iconBg : 'bg-rose-500/15 dark:bg-rose-500/20' ,
47+ iconColor : 'text-rose-600 dark:text-rose-400' ,
48+ glow : '244,63,94' ,
49+ border : 'hover:border-rose-400/50 dark:hover:border-rose-500/50' ,
50+ } ,
51+ {
52+ icon : Globe ,
53+ title : 'Export & Share' ,
54+ description : 'Export activity reports and share insights with your team through various formats and integrations.' ,
55+ iconBg : 'bg-cyan-500/15 dark:bg-cyan-500/20' ,
56+ iconColor : 'text-cyan-600 dark:text-cyan-400' ,
57+ glow : '6,182,212' ,
58+ border : 'hover:border-cyan-400/50 dark:hover:border-cyan-500/50' ,
59+ } ,
60+ ] ;
61+
62+ const containerVariants = {
63+ hidden : { } ,
64+ visible : { transition : { staggerChildren : 0.08 } } ,
65+ } ;
66+
67+ const cardVariants = {
68+ hidden : { opacity : 0 , y : 28 , filter : 'blur(6px)' } ,
69+ visible : {
70+ opacity : 1 ,
71+ y : 0 ,
72+ filter : 'blur(0px)' ,
73+ transition : { type : 'spring' , stiffness : 70 , damping : 18 } ,
74+ } ,
75+ } ;
76+
77+ const FeatureCard = ( { feature } : { feature : typeof features [ 0 ] } ) => {
78+ const ref = useRef < HTMLDivElement > ( null ) ;
79+ const [ hovered , setHovered ] = useState ( false ) ;
80+
81+ const x = useMotionValue ( 0 ) ;
82+ const y = useMotionValue ( 0 ) ;
83+
84+ const rotateX = useSpring ( useTransform ( y , [ - 0.5 , 0.5 ] , [ 5 , - 5 ] ) , {
85+ stiffness : 250 ,
86+ damping : 28 ,
87+ } ) ;
88+ const rotateY = useSpring ( useTransform ( x , [ - 0.5 , 0.5 ] , [ - 5 , 5 ] ) , {
89+ stiffness : 250 ,
90+ damping : 28 ,
91+ } ) ;
92+
93+ const handleMouseMove = ( e : React . MouseEvent < HTMLDivElement > ) => {
94+ if ( ! ref . current ) return ;
95+ const rect = ref . current . getBoundingClientRect ( ) ;
96+ x . set ( ( e . clientX - rect . left ) / rect . width - 0.5 ) ;
97+ y . set ( ( e . clientY - rect . top ) / rect . height - 0.5 ) ;
98+ } ;
99+
100+ const handleMouseLeave = ( ) => {
101+ x . set ( 0 ) ;
102+ y . set ( 0 ) ;
103+ setHovered ( false ) ;
104+ } ;
105+
106+ const Icon = feature . icon ;
107+
108+ return (
109+ < motion . div
110+ variants = { cardVariants }
111+ ref = { ref }
112+ onMouseMove = { handleMouseMove }
113+ onMouseEnter = { ( ) => setHovered ( true ) }
114+ onMouseLeave = { handleMouseLeave }
115+ style = { { rotateX, rotateY, transformStyle : 'preserve-3d' } }
116+ whileHover = { { y : - 8 , scale : 1.02 } }
117+ transition = { { type : 'spring' , stiffness : 280 , damping : 22 } }
118+ className = { `group relative rounded-2xl border border-gray-200 dark:border-white/[0.08] ${ feature . border }
119+ bg-white dark:bg-white/[0.03] backdrop-blur-md
120+ shadow-sm hover:shadow-2xl
121+ transition-colors duration-300 cursor-default overflow-hidden` }
122+ >
123+ { /* Strong ambient glow on hover */ }
124+ < div
125+ className = "absolute inset-0 rounded-2xl pointer-events-none transition-opacity duration-400"
126+ style = { {
127+ opacity : hovered ? 1 : 0 ,
128+ background : `radial-gradient(ellipse at 50% 0%, rgba(${ feature . glow } ,0.22) 0%, transparent 60%)` ,
129+ } }
130+ />
60131
132+ { /* Bottom glow puddle */ }
133+ < div
134+ className = "absolute -bottom-6 left-1/2 -translate-x-1/2 w-3/4 h-12 rounded-full pointer-events-none transition-opacity duration-400 blur-xl"
135+ style = { {
136+ opacity : hovered ? 0.5 : 0 ,
137+ background : `rgba(${ feature . glow } , 0.35)` ,
138+ } }
139+ />
140+
141+ { /* Top accent line */ }
142+ < div
143+ className = "absolute top-0 left-0 right-0 h-[2px] rounded-t-2xl pointer-events-none transition-opacity duration-300"
144+ style = { {
145+ opacity : hovered ? 1 : 0 ,
146+ background : `linear-gradient(90deg, transparent, rgba(${ feature . glow } ,0.8), transparent)` ,
147+ } }
148+ />
149+
150+ { /* Card content */ }
151+ < div className = "relative z-10 p-7 min-h-[230px] flex flex-col" >
152+ { /* Icon */ }
153+ < motion . div
154+ className = { `${ feature . iconBg } w-14 h-14 rounded-xl flex items-center justify-center mb-5` }
155+ animate = {
156+ hovered
157+ ? { rotate : 8 , scale : 1.12 }
158+ : { rotate : 0 , scale : 1 }
159+ }
160+ transition = { { type : 'spring' , stiffness : 350 , damping : 16 } }
161+ >
162+ < Icon className = { `h-6 w-6 ${ feature . iconColor } ` } />
163+ </ motion . div >
164+
165+ { /* Title */ }
166+ < h3 className = "text-xl font-semibold text-gray-900 dark:text-white mb-3 tracking-tight leading-snug" >
167+ { feature . title }
168+ </ h3 >
169+
170+ { /* Description */ }
171+ < p className = "text-base text-gray-500 dark:text-gray-400 leading-relaxed" >
172+ { feature . description }
173+ </ p >
174+ </ div >
175+ </ motion . div >
176+ ) ;
177+ } ;
178+
179+ const Features = ( ) => {
61180 return (
62- < section id = "features" className = "px-6 py-6 bg-white dark:bg-gray-900 transition-colors duration-300" >
63- < div className = "mx-auto" >
64- < div className = "text-center mb-16" >
65- < h2 className = "text-3xl font-bold text-gray-900 dark:text-white mb-4" > Powerful Features</ h2 >
66- < p className = "text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto" >
67- Everything you need to track, analyze, and understand GitHub activity patterns
68- </ p >
69- </ div >
70-
71- < div className = "grid md:grid-cols-2 lg:grid-cols-3 gap-8" >
72- { features . map ( ( feature , index ) => {
73- const IconComponent = feature . icon ;
74- return (
75- < div key = { index } className = { `group h-72 w-full bg-gray-100 dark:bg-gray-800 ${ feature . hoverColor } ${ feature . borderColor } rounded-2xl shadow-md hover:shadow-2xl hover:shadow-blue-500/20 border dark:border-gray-800 transform hover:-translate-y-3 hover:scale-105 backdrop-blur-sm transition-all duration-300 ease-linear p-6` } >
76- < div className = { `${ feature . bgColor } w-12 h-12 rounded-lg flex items-center justify-center mb-6 transition-transform duration-300 group-hover:rotate-6 group-hover:scale-110` } >
77- < IconComponent className = { `h-6 w-6 ${ feature . iconColor } ` } />
78- </ div >
79- < h3 className = " text-2xl font-bold text-gray-900 dark:text-gray-100 group-hover:text-black dark:group-hover:text-white transition-colors duration-300" > { feature . title } </ h3 >
80- < p className = "text-gray-600 dark:text-gray-300 text-base font-semibold leading-relaxed group-hover:text-gray-700 dark:group-hover:text-gray-200 transition-colors duration-300" >
81- { feature . description }
82- </ p >
83- </ div >
84- ) ;
85- } ) }
86- </ div >
181+ < section
182+ id = "features"
183+ className = "relative py-16 overflow-hidden transition-colors duration-300"
184+ >
185+ { /* Dot grid */ }
186+ < div
187+ className = "pointer-events-none absolute inset-0 opacity-[0.03] dark:opacity-[0.07]"
188+ style = { {
189+ backgroundImage :
190+ 'radial-gradient(circle, #94a3b8 1px, transparent 1px)' ,
191+ backgroundSize : '28px 28px' ,
192+ } }
193+ />
194+
195+ { /* Ambient blobs */ }
196+ < div className = "pointer-events-none absolute -top-48 -left-48 w-[500px] h-[500px] rounded-full bg-blue-400/10 dark:bg-blue-500/10 blur-[100px]" />
197+ < div className = "pointer-events-none absolute -bottom-48 -right-48 w-[500px] h-[500px] rounded-full bg-violet-400/10 dark:bg-violet-500/10 blur-[100px]" />
198+ < div className = "pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96 h-96 rounded-full bg-indigo-300/5 dark:bg-indigo-500/5 blur-[80px]" />
199+
200+ < div className = "relative max-w-5xl mx-auto px-4" >
201+ { /* Header */ }
202+ < motion . div
203+ className = "text-center mb-14"
204+ initial = { { opacity : 0 , y : 20 } }
205+ whileInView = { { opacity : 1 , y : 0 } }
206+ viewport = { { once : true } }
207+ transition = { { duration : 0.55 , ease : 'easeOut' } }
208+ >
209+ < h2 className = "text-4xl font-bold text-gray-900 dark:text-white mb-5 tracking-tight" >
210+ Powerful Features
211+ </ h2 >
212+
213+ { /* Premium pill subtitle — no eyebrow badge */ }
214+ < div className = "inline-flex items-center gap-3 px-6 py-3 rounded-full border border-blue-200 dark:border-blue-500/20 bg-blue-50 dark:bg-blue-500/10 backdrop-blur-sm shadow-md shadow-gray-100 dark:shadow-none" >
215+ < span className = "w-2 h-2 rounded-full bg-blue-500 animate-pulse flex-shrink-0" />
216+ < p className = "text-sm text-blue-700 dark:text-blue-300 font-medium" >
217+ Everything you need to track, analyze, and understand GitHub activity patterns
218+ </ p >
219+ < span className = "w-2 h-2 rounded-full bg-blue-500 animate-pulse flex-shrink-0" />
220+ </ div >
221+ </ motion . div >
222+
223+ { /* Cards grid */ }
224+ < motion . div
225+ className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 auto-rows-fr"
226+ variants = { containerVariants }
227+ initial = "hidden"
228+ whileInView = "visible"
229+ viewport = { { once : true , margin : '-50px' } }
230+ >
231+ { features . map ( ( feature ) => (
232+ < FeatureCard key = { feature . title } feature = { feature } />
233+ ) ) }
234+ </ motion . div >
87235 </ div >
88236 </ section >
89237 ) ;
90238} ;
91239
92- export default Features ;
240+ export default Features ;
0 commit comments