@@ -4,8 +4,10 @@ import { Button } from "@/components/ui/button";
44import Link from "next/link" ;
55import Head from "next/head" ;
66import { CodeCell } from "@betteridea/codecell" ;
7+ import { useState , useEffect } from "react" ;
8+ import { FaGreaterThan } from "react-icons/fa6" ;
79
8- import { FaDiscord , FaGithub , FaGreaterThan , FaLessThan , FaLinkedin , FaTwitter , FaXTwitter } from "react-icons/fa6"
10+ import { FaDiscord , FaGithub , FaLessThan , FaLinkedin , FaTwitter , FaXTwitter } from "react-icons/fa6"
911import { TbMailFilled } from "react-icons/tb"
1012
1113import pattern from "@/assets/pattern.svg" ;
@@ -17,6 +19,7 @@ import logo from "@/assets/logo.png";
1719import mirror from "@/assets/mirror.png" ;
1820import arnode from "@/assets/arnode.png" ;
1921import aoxpress from "@/assets/aoxpress.png" ;
22+ import luax from "@/assets/luax.png" ;
2023
2124
2225type TProduct = {
@@ -73,20 +76,27 @@ const products: TProduct[] = [
7376 heading : "LuaX" ,
7477 title : "JSX for Lua" ,
7578 description : "Write JSX like syntax in Lua and serve them using aoxpress" ,
76- image : undefined ,
79+ image : luax ,
7780 link : "https://github.com/ankushKun/aoxpress/tree/main/luax"
7881 }
7982]
8083
8184function Navbar ( ) {
8285 const items = [
83- // { name: "Home", href: "#home" },
8486 { name : "Products" , href : "#products" } ,
8587 { name : "Team" , href : "#team" } ,
8688 { name : "Contact" , href : "#contact" } ,
8789 { name : "Docs" , href : "https://docs.betteridea.dev" } ,
8890 ]
8991
92+ const handleClick = ( e : React . MouseEvent < HTMLAnchorElement > , href : string ) => {
93+ if ( href . startsWith ( '#' ) ) {
94+ e . preventDefault ( ) ;
95+ const element = document . querySelector ( href ) ;
96+ element ?. scrollIntoView ( { behavior : 'smooth' } ) ;
97+ }
98+ } ;
99+
90100 const latestActiveUrl = typeof window !== 'undefined' ? window . location . href : '' ;
91101 const activeUrl = latestActiveUrl . split ( '#' ) [ 1 ] ;
92102
@@ -95,7 +105,7 @@ function Navbar() {
95105 < div className = "flex gap-1" >
96106 {
97107 items . map ( item => (
98- < Link href = { item . href } key = { item . name } >
108+ < Link href = { item . href } key = { item . name } onClick = { ( e ) => handleClick ( e , item . href ) } >
99109 < Button data-active = { ( "#" + activeUrl ) . endsWith ( item . href ) } className = "rounded-full px-4 h-6 text-sm data-[active=true]:bg-primary" variant = "ghost" > { item . name } </ Button >
100110 </ Link >
101111 ) )
@@ -113,23 +123,62 @@ function Product({ heading, title, description, image, link }: {
113123} ) {
114124 return < div className = "mx-auto md:px-24" >
115125 < div className = "text-3xl font-serif-display text-center flex gap-3 items-center relative p-5 px-10 md:px-20 pt-20" > { heading } < div className = "h-[1px] bg-foreground/30 grow" /> </ div >
116- < div className = "mx-10 md:mx-20 p-4 bg-gradient-to-b from-foreground/5 to-white rounded-xl" >
126+ < div className = "mx-10 md:mx-20 p-4 bg-gradient-to-b from-foreground/5 to-white rounded-xl transition-all duration-300 hover:shadow-lg hover:scale-[1.02] " >
117127 < div className = "flex flex-col md:flex-row gap-5 items-center" >
118- < div className = "aspect-square" >
119- < Image src = { image } alt = { title } width = { 500 } height = { 500 } />
128+ < div className = "aspect-square relative" >
129+ < Image
130+ src = { image }
131+ alt = { title }
132+ width = { 500 }
133+ height = { 500 }
134+ />
120135 </ div >
121136 < div className = "md:w-1/2" >
122137 < div className = "text-xl font-bold" > { title } </ div >
123138 < div className = "text-lg text-muted-foreground" > { description } </ div >
124139 < Link href = { link } target = "_blank" >
125- < Button className = "mt-5 rounded-full text-foreground" > Try it yourself < FaGreaterThan className = "scale-x-50 ml-2" /> </ Button >
140+ < Button className = "mt-5 rounded-full text-foreground hover:scale-105 transition-transform " > Try it yourself < FaGreaterThan className = "scale-x-50 ml-2" /> </ Button >
126141 </ Link >
127142 </ div >
128143 </ div >
129144 </ div >
130145 </ div >
131146}
132147
148+ function ScrollToTop ( ) {
149+ const [ isVisible , setIsVisible ] = useState ( false ) ;
150+
151+ useEffect ( ( ) => {
152+ const toggleVisibility = ( ) => {
153+ if ( window . pageYOffset > 300 ) {
154+ setIsVisible ( true ) ;
155+ } else {
156+ setIsVisible ( false ) ;
157+ }
158+ } ;
159+
160+ window . addEventListener ( 'scroll' , toggleVisibility ) ;
161+ return ( ) => window . removeEventListener ( 'scroll' , toggleVisibility ) ;
162+ } , [ ] ) ;
163+
164+ const scrollToTop = ( ) => {
165+ window . scrollTo ( {
166+ top : 0 ,
167+ behavior : 'smooth' ,
168+ } ) ;
169+ } ;
170+
171+ return (
172+ < button
173+ onClick = { scrollToTop }
174+ className = { `fixed bottom-4 right-4 p-3 rounded-full bg-primary text-background transition-opacity duration-300 ${ isVisible ? 'opacity-100' : 'opacity-0'
175+ } `}
176+ >
177+ < FaGreaterThan className = "rotate-[-90deg]" />
178+ </ button >
179+ ) ;
180+ }
181+
133182export default function Home ( ) {
134183 return (
135184 < main >
@@ -196,6 +245,7 @@ export default function Home() {
196245 </ div >
197246 </ Link >
198247 </ footer >
248+ < ScrollToTop />
199249 </ main >
200250 ) ;
201251}
0 commit comments