feat: enhance layout and navigation with smooth scrolling and section IDs
This commit is contained in:
parent
6664274403
commit
293dafb4ee
@ -92,7 +92,7 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={openSauceOne.variable}>
|
<html lang="en" className={`${openSauceOne.variable} scroll-smooth`}>
|
||||||
<body className="min-h-screen w-full flex flex-col">
|
<body className="min-h-screen w-full flex flex-col">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div>{children}</div>
|
<div>{children}</div>
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export default function PortFolio() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col md:flex-row md:px-20 md:py-16">
|
<div id="about-us" className="flex flex-col md:flex-row md:px-20 md:py-16">
|
||||||
<div className="flex flex-col gap-4 py-6 px-4 md:w-1/2 md:pr-20 md:gap-6 md:px-0 md:py-0">
|
<div className="flex flex-col gap-4 py-6 px-4 md:w-1/2 md:pr-20 md:gap-6 md:px-0 md:py-0">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<p className="text-secondary-400 text-[13px] md:text-sm">ABOUT US</p>
|
<p className="text-secondary-400 text-[13px] md:text-sm">ABOUT US</p>
|
||||||
@ -95,7 +95,7 @@ export default function PortFolio() {
|
|||||||
<Image src={AboutUsImage} alt="about-us" className="w-full md:w-1/2 object-contain" />
|
<Image src={AboutUsImage} alt="about-us" className="w-full md:w-1/2 object-contain" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 px-4 py-6 md:px-20 md:py-16 md:gap-6">
|
<div id="services" className="flex flex-col gap-4 px-4 py-6 md:px-20 md:py-16 md:gap-6">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<p className="text-[13px] md:text-sm text-secondary-400">SERVICES</p>
|
<p className="text-[13px] md:text-sm text-secondary-400">SERVICES</p>
|
||||||
<p className="text-[32px] md:text-[40px] text-title font-semibold">Our Services</p>
|
<p className="text-[32px] md:text-[40px] text-title font-semibold">Our Services</p>
|
||||||
@ -113,7 +113,7 @@ export default function PortFolio() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col px-4 py-6 gap-4 bg-linear-to-b from-subtle to-white md:py-16 md:px-20 md:gap-10">
|
<div id="portfolio" className="flex flex-col px-4 py-6 gap-4 bg-linear-to-b from-subtle to-white md:py-16 md:px-20 md:gap-10">
|
||||||
<div className="flex flex-col gap-4 md:gap-6">
|
<div className="flex flex-col gap-4 md:gap-6">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<p className="text-[13px] text-secondary-400 md:text-sm">PORTFOLIO</p>
|
<p className="text-[13px] text-secondary-400 md:text-sm">PORTFOLIO</p>
|
||||||
@ -148,7 +148,7 @@ export default function PortFolio() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative">
|
<div id="process" className="relative">
|
||||||
<div className="flex flex-col md:py-16 md:px-20 md:grid md:grid-cols-2 md:gap-6">
|
<div className="flex flex-col md:py-16 md:px-20 md:grid md:grid-cols-2 md:gap-6">
|
||||||
<div className="flex flex-col gap-4 px-4 py-6 z-10 md:gap-6">
|
<div className="flex flex-col gap-4 px-4 py-6 z-10 md:gap-6">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import Image from "next/image";
|
|||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-primary-800 w-full relative">
|
<div id="kontak" className="bg-primary-800 w-full relative">
|
||||||
<div className="flex flex-col gap-4 px-4 py-6 z-10 text-white md:py-16 md:px-20 md:grid md:grid-cols-2 md:gap-6">
|
<div className="flex flex-col gap-4 px-4 py-6 z-10 text-white md:py-16 md:px-20 md:grid md:grid-cols-2 md:gap-6">
|
||||||
<div className="flex flex-col gap-4 md:justify-between">
|
<div className="flex flex-col gap-4 md:justify-between">
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
|
|||||||
@ -1,32 +1,70 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Logo from "@/image/Logo.svg";
|
import Logo from "@/image/Logo.svg";
|
||||||
import { ListIcon } from "@phosphor-icons/react/dist/ssr";
|
import { ListIcon, XIcon } from "@phosphor-icons/react/dist/ssr";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
const pathname = usePathname();
|
const [open, setOpen] = useState(false);
|
||||||
|
const [active, setActive] = useState("about-us");
|
||||||
|
|
||||||
const menu = [
|
const menu = [
|
||||||
{ label: "About Us", url: "/" },
|
{ label: "About Us", url: "/portfolio#about-us", id: "about-us" },
|
||||||
{ label: "Services", url: "/" },
|
{ label: "Services", url: "/portfolio#services", id: "services" },
|
||||||
{ label: "Portfolio", url: "/portfolio" },
|
{ label: "Portfolio", url: "/portfolio#portfolio", id: "portfolio" },
|
||||||
{ label: "Process", url: "/" },
|
{ label: "Process", url: "/portfolio#process", id: "process" },
|
||||||
{ label: "Kontak", url: "/" },
|
{ label: "Kontak", url: "/portfolio#kontak", id: "kontak" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const ids = ["about-us", "services", "portfolio", "process", "kontak"];
|
||||||
|
const sections = ids.map((id) => document.getElementById(id)).filter(Boolean) as HTMLElement[];
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) setActive(entry.target.id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ rootMargin: "-50% 0px -50% 0px" }
|
||||||
|
);
|
||||||
|
sections.forEach((section) => observer.observe(section));
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="bg-white px-4 h-19.5 md:h-18.5 flex items-center w-full justify-between md:py-5.5 md:px-16 sticky top-0 left-0 right-0 z-50">
|
<div className="bg-white px-4 h-19.5 md:h-18.5 flex items-center w-full justify-between md:py-5.5 md:px-16 sticky top-0 left-0 right-0 z-50">
|
||||||
<Image src={Logo} width={118} className="w-fit h-7.5" alt="logo" />
|
<Image src={Logo} width={118} className="w-fit h-7.5" alt="logo" />
|
||||||
<ListIcon className="size-8 text-secondary-400 cursor-pointer md:hidden" />
|
<button onClick={() => setOpen(true)} className="md:hidden">
|
||||||
|
<ListIcon className="size-8 text-secondary-400 cursor-pointer" />
|
||||||
|
</button>
|
||||||
<div className="md:flex gap-7.5 hidden">
|
<div className="md:flex gap-7.5 hidden">
|
||||||
{menu?.map((item) => (
|
{menu?.map((item) => (
|
||||||
<Link href={item?.url} key={item?.label}>
|
<Link href={item.url} key={item.label}>
|
||||||
<div className={`font-medium ${pathname === item?.url ? "text-primary-800" : "text-title"}`}>{item?.label}</div>
|
<div className={`font-medium ${active === item.id ? "text-primary-800" : "text-title"}`}>{item.label}</div>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{open && <div className="fixed inset-0 bg-black/50 z-50 md:hidden" onClick={() => setOpen(false)} />}
|
||||||
|
|
||||||
|
<div className={`fixed top-0 right-0 h-full w-64 bg-white z-50 transform transition-transform duration-300 md:hidden ${open ? "translate-x-0" : "translate-x-full"}`}>
|
||||||
|
<div className="flex justify-between items-center p-4">
|
||||||
|
<Image src={Logo} width={118} className="w-fit h-7.5" alt="logo" />
|
||||||
|
<button onClick={() => setOpen(false)}>
|
||||||
|
<XIcon className="size-6 text-secondary-400" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-4 p-4">
|
||||||
|
{menu?.map((item) => (
|
||||||
|
<Link href={item.url} key={item.label} onClick={() => setOpen(false)}>
|
||||||
|
<div className={`font-medium ${active === item.id ? "text-primary-800" : "text-title"}`}>{item.label}</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user