Files
examjam-frontend/torpedo/app/page.tsx
2025-07-03 01:43:25 +06:00

85 lines
2.1 KiB
TypeScript

"use client";
import { Button } from "@/components/ui/button";
import Image from "next/image";
import { useRef, useState } from "react";
import { motion } from "framer-motion";
interface Position {
left: number;
width: number;
opacity: number;
}
interface TabProps {
children: React.ReactNode;
setPosition: (position: Position) => void;
}
const Slidetabs: React.FC = () => {
const [position, setPosition] = useState<Position>({
left: 60,
width: 150,
opacity: 1,
});
return (
<ul className="relative mx-auto flex w-fit rounded-full border-2 border-black bg-white p-1">
<Tab setPosition={setPosition}>Home</Tab>
<Tab setPosition={setPosition}>Features</Tab>
<Tab setPosition={setPosition}>Pricing</Tab>
<Tab setPosition={setPosition}>Docs</Tab>
<Tab setPosition={setPosition}>Blog</Tab>
<Cursor position={position} />
</ul>
);
};
const Tab: React.FC<TabProps> = ({ children, setPosition }) => {
const ref = useRef<HTMLLIElement | null>(null);
return (
<li
ref={ref}
onMouseEnter={() => {
if (!ref.current) return;
const { width } = ref.current.getBoundingClientRect();
setPosition({
width,
opacity: 1,
left: ref.current.offsetLeft,
});
}}
className="relative z-10 block cursor-pointer px-3 py-1.5 text-xs uppercase text-white mix-blend-difference md:px-5 md:py-3 md:text-base"
>
{children}
</li>
);
};
const Cursor: React.FC<{ position: Position }> = ({ position }) => {
return (
<motion.li
animate={position}
className="absolute z-0 w-36 h-7 rounded-full bg-black md:h-12"
></motion.li>
);
};
export default function Home() {
return (
<body className="">
<header className="flex justify-between">
<div className="">
<Image src="/logo/logo-full.svg" alt="logo" width={200} height={0} />
</div>
<nav>
<Slidetabs />
</nav>
<div>
<Button>Login</Button>
</div>
</header>
<main className="text-7xl">Welcome to Torpedo</main>
</body>
);
}