vkorobtsev-nextJs/components/Navbar.jsx

227 lines
5.5 KiB
React
Raw Normal View History

2023-08-30 19:06:48 +07:00
"use client";
2023-09-02 11:12:47 +07:00
import { useRef, useState, useEffect } from "react";
import { motion } from "framer-motion";
2023-09-02 21:59:30 +07:00
import Link from "next/link";
2023-09-02 11:12:47 +07:00
2023-09-03 13:23:39 +07:00
const NavItems = ({ isNavOpen, setIsNavOpen }) => {
const [isMobile, setIsMobile] = useState(false);
const handleItemClick = () => {
setIsNavOpen(false);
};
2023-09-02 11:12:47 +07:00
const navVariant = {
2023-09-06 17:04:47 +07:00
open: {
clipPath: `circle(1920px at calc(100% - 40px) 40px)`,
2023-09-02 11:12:47 +07:00
transition: {
type: "spring",
stiffness: 400,
damping: 40,
2023-09-02 11:12:47 +07:00
},
2023-09-06 17:04:47 +07:00
},
2023-09-02 11:12:47 +07:00
closed: {
clipPath: "circle(0px at calc(100% - 120px) 35px)",
transition: {
delay: 0.5,
type: "spring",
stiffness: 400,
2023-09-02 21:23:37 +07:00
damping: 30,
2023-09-02 11:12:47 +07:00
},
},
};
2023-09-03 13:23:39 +07:00
useEffect(() => {
const updateScreenWidth = () => {
setIsMobile(window.innerWidth <= 768);
};
2023-09-02 11:12:47 +07:00
2023-09-03 13:23:39 +07:00
// Initial check and event listener
updateScreenWidth();
window.addEventListener("resize", updateScreenWidth);
2023-09-02 11:12:47 +07:00
2023-09-03 13:23:39 +07:00
// Clean up the event listener on unmount
return () => {
window.removeEventListener("resize", updateScreenWidth);
};
}, []);
2023-09-02 11:12:47 +07:00
2023-09-03 13:23:39 +07:00
// Check screen width and adjust clipPath for smaller screens
if (isMobile) {
(navVariant.open = {
clipPath: `circle(1920px at calc(100% - 40px) 40px)`,
2023-09-03 13:23:39 +07:00
transition: {
type: "tween",
2023-09-03 13:23:39 +07:00
},
}),
(navVariant.closed = {
clipPath: "circle(0px at calc(100% - 35px) 35px)",
transition: {
delay: 0.5,
type: "spring",
stiffness: 400,
damping: 40,
},
});
2023-09-03 13:23:39 +07:00
} else {
(navVariant.open = {
2023-12-16 11:02:18 +07:00
clipPath: `circle(2444px at calc(100% - 40px) 40px)`,
2023-09-03 13:23:39 +07:00
transition: {
type: "spring",
stiffness: 400,
damping: 40,
},
}),
(navVariant.closed = {
clipPath: "circle(0px at calc(100% - 120px) 35px)",
transition: {
delay: 0.5,
type: "spring",
stiffness: 400,
damping: 40,
},
});
2023-09-03 13:23:39 +07:00
}
2023-09-02 11:12:47 +07:00
const itemVariants = {
open: (custom) => ({
2023-09-02 11:12:47 +07:00
opacity: 1,
x: 0,
2023-09-02 11:12:47 +07:00
rotate: 0,
transition: {
delay: custom,
type: "spring",
stiffness: 400,
damping: 40,
},
}),
2023-09-02 11:12:47 +07:00
closed: {
opacity: 0,
x: -80,
2023-09-02 11:12:47 +07:00
rotate: 0,
transition: {
type: "spring",
stiffness: 400,
damping: 40,
},
2023-09-02 11:12:47 +07:00
},
};
return (
<>
<motion.div
className={`fixed z-[45] w-full h-screen flex items-center justify-center backdrop-blur-sm transition-all ease duration-700 overflow-hidden`}
2023-09-02 11:12:47 +07:00
variants={navVariant}
animate={isNavOpen ? "open" : "closed"}
initial={false}>
<div className="relative backdrop-blur-sm opacity-95 flex flex-col items-center space-x-8 min-h-[100vh] bg-gray-700 min-w-[100vw] ">
<div className="flex flex-col items-center space-y-8 my-auto mx-0 z-50">
2023-09-03 13:23:39 +07:00
{/* title */}
<motion.h1
variants={itemVariants}
animate={isNavOpen ? "open" : "closed"}
2023-09-05 20:06:59 +07:00
className="text-6xl font-bold text-white ">
2023-09-03 13:23:39 +07:00
Menu
</motion.h1>
<Link href="/#home">
2023-09-03 13:23:39 +07:00
<div
className="text-2xl font-bold text-white"
onClick={handleItemClick}>
2023-09-03 13:23:39 +07:00
<motion.h2
className="text-white"
variants={itemVariants}
animate={isNavOpen ? "open" : "closed"}
custom={0.1}>
2023-09-03 13:23:39 +07:00
Home
</motion.h2>
</div>
</Link>
2023-09-03 13:23:39 +07:00
<Link href="/about">
<div
onClick={handleItemClick}
className="text-2xl font-bold text-white">
2023-09-03 13:23:39 +07:00
<motion.h2
className="text-white"
variants={itemVariants}
animate={isNavOpen ? "open" : "closed"}
custom={0.2}>
2023-09-03 13:23:39 +07:00
About
</motion.h2>
</div>
</Link>
<Link href="/projects">
<div
onClick={handleItemClick}
className="text-2xl font-bold text-white">
2023-09-03 13:23:39 +07:00
<motion.h2
className="text-white"
variants={itemVariants}
animate={isNavOpen ? "open" : "closed"}
custom={0.3}>
2023-09-03 13:23:39 +07:00
Projects
</motion.h2>
</div>
</Link>
<Link href="/#contact">
2023-09-03 13:23:39 +07:00
<div
onClick={handleItemClick}
className="text-2xl font-bold text-white">
2023-09-03 13:23:39 +07:00
<motion.h2
className="text-white"
variants={itemVariants}
animate={isNavOpen ? "open" : "closed"}
custom={0.4}>
2023-09-03 13:23:39 +07:00
Contact
</motion.h2>
</div>
</Link>
2023-09-03 13:23:39 +07:00
</div>
</div>
2023-09-02 11:12:47 +07:00
</motion.div>
</>
);
};
2023-08-30 19:06:48 +07:00
const Navbar = () => {
const navRef = useRef(null);
const [isNavOpen, setIsNavOpen] = useState(false);
const toggleNav = () => {
setIsNavOpen(!isNavOpen);
};
return (
<>
<nav
ref={navRef}
2023-09-03 13:23:39 +07:00
className={`navbar px-5 md:px-24 w-screen fixed transition-colors ease duration-500 ${
isNavOpen
? "backdrop-filter backdrop-blur-md bg-gray-700 bg-opacity-50"
: "backdrop-filter backdrop-blur-md"
2023-09-05 20:06:59 +07:00
} inset-0 bg-opacity-50 flex flex-row justify-between items-center h-16 z-50 `}>
<div>
<h1
className={`text-2xl ml-2 md:ml-0 transition-colors ease duration-500 ${
isNavOpen ? "text-white" : ""
}`}>
Korobtsev
</h1>
2023-08-30 19:06:48 +07:00
</div>
<div className="flex flex-row items-center">
<button
2023-09-03 08:45:12 +07:00
className="burger button flex flex-col justify-center items-center space-y-1.5 "
2023-08-30 19:06:48 +07:00
onClick={toggleNav}>
<div
2023-09-04 22:10:11 +07:00
className={`w-10 h-1 bg-black rounded-full transition-all ease duration-300 ${
isNavOpen ? "rotate-45 bg-white translate-y-[2px]" : ""
2023-09-02 11:12:47 +07:00
}`}></div>
2023-08-30 19:06:48 +07:00
<div
2023-09-04 22:10:11 +07:00
className={`w-10 h-1 bg-black rounded-full transition-all ease duration-300 ${
isNavOpen ? "-rotate-45 -translate-y-2 bg-white" : ""
2023-09-02 11:12:47 +07:00
}`}></div>
2023-08-30 19:06:48 +07:00
</button>
</div>
</nav>
{/* items */}
<NavItems isNavOpen={isNavOpen} setIsNavOpen={setIsNavOpen} />
2023-08-30 19:06:48 +07:00
</>
);
};
export default Navbar;