1- " use client" ;
1+ ' use client' ;
22
3- import Link from " next/link" ;
4- import { useState , useEffect } from " react" ;
5- import Companies from " @/components/companies" ;
6- import TodoDemo from " @/components/todo-demo" ;
7- import InstallGuide from " @/components/install-guide" ;
3+ import Link from ' next/link' ;
4+ import { useState , useEffect } from ' react' ;
5+ import Companies from ' @/components/companies' ;
6+ import TodoDemo from ' @/components/todo-demo' ;
7+ import InstallGuide from ' @/components/install-guide' ;
88
99export default function Home ( ) {
1010 const [ showDemo , setShowDemo ] = useState ( false ) ;
1111 const [ isMobile , setIsMobile ] = useState ( false ) ;
12+ const [ showBanner , setShowBanner ] = useState ( false ) ;
1213
1314 useEffect ( ( ) => {
1415 const checkMobile = ( ) => {
1516 setIsMobile ( window . innerWidth < 768 ) ;
1617 } ;
1718
1819 checkMobile ( ) ;
19- window . addEventListener ( " resize" , checkMobile ) ;
20- return ( ) => window . removeEventListener ( " resize" , checkMobile ) ;
20+ window . addEventListener ( ' resize' , checkMobile ) ;
21+ return ( ) => window . removeEventListener ( ' resize' , checkMobile ) ;
2122 } , [ ] ) ;
2223
24+ useEffect ( ( ) => {
25+ const bannerClosed = localStorage . getItem ( 'reactGrabBannerClosed' ) ;
26+ if ( ! bannerClosed ) {
27+ setShowBanner ( true ) ;
28+ }
29+ } , [ ] ) ;
30+
31+ const handleCloseBanner = ( ) => {
32+ setShowBanner ( false ) ;
33+ localStorage . setItem ( 'reactGrabBannerClosed' , 'true' ) ;
34+ } ;
35+
2336 return (
2437 < div className = "mx-auto max-w-xl" >
2538 < div className = "mt-8 space-y-4" >
39+ { showBanner && (
40+ < div className = "relative bg-[#4B4DB3]/5 border border-[#4B4DB3]/20 rounded p-4" >
41+ < button
42+ onClick = { handleCloseBanner }
43+ className = "absolute top-3 right-3 text-neutral-500 hover:text-neutral-700 transition-colors"
44+ aria-label = "Close banner"
45+ >
46+ < svg
47+ xmlns = "http://www.w3.org/2000/svg"
48+ width = "18"
49+ height = "18"
50+ viewBox = "0 0 24 24"
51+ fill = "none"
52+ stroke = "currentColor"
53+ strokeWidth = "2"
54+ strokeLinecap = "round"
55+ strokeLinejoin = "round"
56+ >
57+ < line x1 = "18" y1 = "6" x2 = "6" y2 = "18" />
58+ < line x1 = "6" y1 = "6" x2 = "18" y2 = "18" />
59+ </ svg >
60+ </ button >
61+ < div className = "pr-6 space-y-2" >
62+ < div className = "text-sm" >
63+ < span className = "font-medium text-[#4B4DB3]" >
64+ 🎉 I'm working on something new (still free + open
65+ source!)
66+ </ span >
67+ </ div >
68+ < div className = "text-sm text-neutral-700" >
69+ React Grab allows you to select an element and copy its context
70+ (like HTML, React component, and file source)
71+ </ div >
72+ < div className = "mt-3" >
73+ < Link
74+ href = "https://react-grab.com"
75+ target = "_blank"
76+ rel = "noopener noreferrer"
77+ className = "inline-flex items-center gap-2 bg-[#4B4DB3] hover:bg-[#3a3d8f] text-white px-4 py-2 text-sm font-medium transition-colors"
78+ >
79+ Check it out: react-grab.com
80+ < OutBoundLinkIcon size = { 14 } />
81+ </ Link >
82+ </ div >
83+ </ div >
84+ </ div >
85+ ) }
86+
2687 < div >
27- React Scan automatically detects performance issues in your React app{ " " }
28- < div className = { `flex ${ ! isMobile ? " visible" : " hidden" } ` } >
88+ React Scan automatically detects performance issues in your React app{ ' ' }
89+ < div className = { `flex ${ ! isMobile ? ' visible' : ' hidden' } ` } >
2990 < button
3091 onClick = { ( ) => setShowDemo ( ! showDemo ) }
3192 className = "mt-2 border border-gray-300 bg-white px-3 py-1 text-sm font-medium text-neutral-600 hover:bg-gray-50 hover:text-black transition-colors"
3293 >
33- { showDemo ? " Hide demo" : " Show demo" }
94+ { showDemo ? ' Hide demo' : ' Show demo' }
3495 </ button >
3596 </ div >
3697 </ div >
@@ -67,17 +128,11 @@ export default function Home() {
67128 href = "https://github.com/aidenybai/react-scan#install"
68129 className = "flex-3 sm:flex-initial sm:w-auto w-full order-2 sm:order-1 inline-block bg-black px-9 py-2 font-medium whitespace-nowrap text-white text-center"
69130 >
70- Get started { "»" }
71- </ Link >
72- < Link
73- href = "/monitoring"
74- className = "flex-2 order-1 sm:order-2 inline-block border-2 border-black px-5 py-2 font-medium whitespace-nowrap text-center"
75- >
76- React Scan Monitoring
131+ Get started { '»' }
77132 </ Link >
78133 < Link
79134 href = "https://discord.gg/KV3FhDq7FA"
80- className = "flex-1 order-1 sm:order-3 bg-[#5865F2] px-2 py-2 font-medium whitespace-nowrap text-white text-center flex items-center justify-center gap-x-1"
135+ className = "flex-1 order-1 sm:order-2 bg-[#5865F2] px-2 py-2 font-medium whitespace-nowrap text-white text-center flex items-center justify-center gap-x-1"
81136 >
82137 < span > Join Discord</ span >
83138 < OutBoundLinkIcon size = { 18 } />
@@ -99,7 +154,7 @@ export default function Home() {
99154 ) ;
100155}
101156
102- const OutBoundLinkIcon = ( { size = 24 , className = "" } ) => {
157+ const OutBoundLinkIcon = ( { size = 24 , className = '' } ) => {
103158 return (
104159 < svg
105160 xmlns = "http://www.w3.org/2000/svg"
0 commit comments