animation changes

This commit is contained in:
Mohammad Yaseen 2025-12-16 12:30:38 +05:30
parent c17c233ba4
commit 5abc04c382
10 changed files with 175 additions and 19 deletions

View File

@ -2,22 +2,33 @@ import type React from "react"
import type { Metadata } from "next" import type { Metadata } from "next"
import { Analytics } from "@vercel/analytics/next" import { Analytics } from "@vercel/analytics/next"
import "./globals.css" import "./globals.css"
import LadderClimb from "@/components/ladderclimber"
import Navbar from "@/components/navbar"
export const metadata: Metadata = { export const metadata: Metadata = {
title: "School For Schools", title: "School For Schools",
description: "Combining expertise in education with cutting-edge technology", description: "Combining expertise in education with cutting-edge technology",
generator: "v0.app",
} }
export default function RootLayout({ export default function RootLayout({ children }: { children: React.ReactNode }) {
children,
}: Readonly<{
children: React.ReactNode
}>) {
return ( return (
<html lang="en"> <html lang="en">
<body className="font-sans antialiased" style={{ fontFamily: "DIN Alternate, sans-serif" }} suppressHydrationWarning> <body
className="font-sans antialiased scrollbar-hide"
style={{ fontFamily: "DIN Alternate, sans-serif", scrollbarWidth: "none", msOverflowStyle: "none" }}
>
<style>{`
html::-webkit-scrollbar,
body::-webkit-scrollbar {
display: none;
}
`}</style>
<Navbar />
{/* LadderClimb is now global */}
<LadderClimb />
{/* All page content */}
{children} {children}
<Analytics /> <Analytics />
</body> </body>

View File

@ -5,11 +5,12 @@ import Testimonials from "@/components/testimonials"
import OurOfferings from "@/components/our-offerings" import OurOfferings from "@/components/our-offerings"
import TrustedBy from "@/components/trusted-by" import TrustedBy from "@/components/trusted-by"
import Footer from "@/components/footer" import Footer from "@/components/footer"
import LadderClimb from "@/components/ladderclimber"
export default function Home() { export default function Home() {
return ( return (
<>
<main className="w-full"> <main className="w-full">
<Navbar />
<MainHero /> <MainHero />
<HeroSection /> {/* This is the 'Why SFS' section */} <HeroSection /> {/* This is the 'Why SFS' section */}
<OurOfferings /> <OurOfferings />
@ -17,5 +18,6 @@ export default function Home() {
<TrustedBy /> <TrustedBy />
<Footer /> <Footer />
</main> </main>
</>
) )
} }

View File

@ -0,0 +1,143 @@
"use client"
import React, { useEffect, useRef, useState } from "react"
export default function LadderClimb() {
const charRef = useRef<HTMLDivElement>(null)
const ladderRef = useRef<HTMLDivElement>(null)
const [animation, setAnimation] = useState<"idle" | "climbing">("idle")
const [visible, setVisible] = useState(true)
const ladderHeight = useRef(0)
const scrollTimeout = useRef<any>(null)
const updateDimensions = () => {
if (ladderRef.current) {
ladderHeight.current = ladderRef.current.clientHeight
}
if (charRef.current) {
charRef.current.style.transform = `translateY(0px)`
}
}
useEffect(() => {
updateDimensions()
setAnimation("idle")
window.addEventListener("resize", updateDimensions)
const handleScroll = () => {
if (!charRef.current || !ladderRef.current) return
// show ladder & climbing animation
setVisible(true)
setAnimation("climbing")
const scrollTop = window.scrollY
const docHeight = document.body.scrollHeight
const viewportHeight = window.innerHeight
let progress = scrollTop / (docHeight - viewportHeight)
progress = Math.max(0, Math.min(1, progress))
const topOffset = 174
const bottomOffset = 30
const maxClimb = ladderHeight.current - topOffset - bottomOffset
const y = progress * maxClimb
charRef.current.style.transform = `translateY(-${y}px)`
// hide smoothly after scroll stops
if (scrollTimeout.current) clearTimeout(scrollTimeout.current)
scrollTimeout.current = setTimeout(() => {
setAnimation("idle")
setVisible(false)
}, 500)
}
window.addEventListener("scroll", handleScroll)
return () => {
window.removeEventListener("scroll", handleScroll)
window.removeEventListener("resize", updateDimensions)
if (scrollTimeout.current) clearTimeout(scrollTimeout.current)
}
}, [])
return (
<>
{/* Ladder container */}
<div
ref={ladderRef}
style={{
position: "fixed",
right: 0,
top: 80,
height: "100vh",
width: "100px",
display: "flex",
justifyContent: "center",
alignItems: "flex-end",
zIndex: 999,
// smooth hide / show
opacity: visible ? 1 : 0,
transform: visible ? "translateX(0)" : "translateX(40px)",
pointerEvents: visible ? "auto" : "none",
transition: "opacity 0.8s ease, transform 0.8s ease"
}}
>
{/* Ladder background */}
<div
style={{
height: "100%",
width: "40px",
background:
"repeating-linear-gradient(to bottom, #666 0, #666 8px, transparent 8px, transparent 30px)",
borderLeft: "8px solid #666",
borderRight: "8px solid #666",
zIndex: 1
}}
/>
{/* Character */}
<div
ref={charRef}
style={{
position: "absolute",
bottom: 45,
left: "50%",
marginLeft: "-100px",
width: "200px",
zIndex: 10,
willChange: "transform",
transition: "transform 0.15s linear"
}}
>
{/* CLIMBING */}
{animation === "climbing" && (
<img
src="./climber21.png"
alt="Climbing"
style={{ width: "400px", height: "200px" }}
/>
)}
{/* IDLE */}
{animation === "idle" && (
<img
src="./Idle3.png"
alt="Idle"
style={{
marginLeft: "10px",
width: "400px",
height: "200px"
}}
/>
)}
</div>
</div>
</>
)
}

View File

@ -75,7 +75,7 @@ export default function Navbar() {
}, []) }, [])
return ( return (
<nav className="w-full bg-white border-b border-gray-200"> <nav className="fixed top-0 left-0 right-0 z-50 w-full bg-white border-b border-gray-200">
<div className="w-full pl-6 sm:pl-8 lg:pl-12 pr-4 sm:pr-6 lg:pr-8"> <div className="w-full pl-6 sm:pl-8 lg:pl-12 pr-4 sm:pr-6 lg:pr-8">
<div className="flex justify-between items-center h-20"> <div className="flex justify-between items-center h-20">
{/* Logo */} {/* Logo */}

BIN
public/Idle1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
public/Idle3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
public/climber2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
public/climber21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
public/ladder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB