next.jsshadcnui

Sheet component from shadcn ui does not close


I'm building a simple navbar using Next.js and the sheet component from shadcnui to handle the mobile version of navigation.

When I click on one of the links in the mobile navbar, I'm correctly redirected to the corresponding page. However, the problem is that the mobile menu (the sheet component) remains open even after redirecting to the new page. I would like the mobile menu to automatically close after clicking on one of the links.

I've divided the code into three main components:

I've tried using the SheetClose component provided by the sheet component to close the mobile menu after clicking on a link, but it doesn't seem to work as expected.

How can I make the mobile menu close automatically after redirecting to a new page?

Header:

"use client";
import { useEffect, useState } from "react";
import Logo from "../Logo";
import MobileNav from "../MobileNav";
import Nav from "../Nav";
import ThemeToggler from "../ThemeToggler";
import { usePathname } from "next/navigation";
import { Sheet, SheetTrigger } from "../ui/sheet";

const Header = () => {
  const [header, setHeader] = useState(false);
  const pathname = usePathname();

  useEffect(() => {
    const handleScroll = () => {
      window.scrollY > 50 ? setHeader(true) : setHeader(false);
    };

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []); // Aggiungi l'array vuoto per eseguire l'effetto solo una volta al montaggio del componente

  return (
    <header
      className={`${
        header
          ? "py-4 bg-white-900/100 backdrop-blur-sm  shadow-lg dark:bg-accent-900/10 dark:backdrop-blur-sm dark:shadow-lg"
          : "py-6 dark:bg-transparent"
      } sticky top-0 z-30 transition-all `}
    >
      <div className="container mx-auto">
        <div className="flex justify-between items-center">
          <Logo />
          <div className="flex items-center gap-x-6">
            <Nav
              containerStyles="hidden xl:flex gap-x-8 items-center"
              linkStyles="relative hover:text-primary transition-all"
              underlineStyles="absolute left-0 top-full h-[2px] bg-primary w-full"
            />
            <ThemeToggler />
            <div className="xl:hidden">
              <MobileNav />
            </div>
          </div>
        </div>
      </div>
    </header>
  );
};

export default Header;

Nav:

import { motion } from "framer-motion";
import Link from "next/link";
import { usePathname } from "next/navigation";
import React from "react";
import { SheetClose } from "./ui/sheet";

interface Props {
  containerStyles?: string;
  linkStyles?: string;
  underlineStyles?: string;
}

const links = [
  { path: "/", name: "home" },
  { path: "/projects", name: "my projects" },
  { path: "/contact", name: "contact" },
];

const Nav = ({ containerStyles, linkStyles, underlineStyles }: Props) => {
  const pathName = usePathname();

  return (
    <nav className={`${containerStyles}`}>
      {links.map((link, index) => (
        <Link
          key={index}
          href={link.path}
          className={`capitalize ${linkStyles}`}
        >
          {link.path === pathName && (
            <motion.span
              initial={{ y: "-100%" }}
              animate={{ y: 0 }}
              transition={{ type: "tween" }}
              layoutId="underline"
              className={`${underlineStyles}`}
            />
          )}
          {link.name}
        </Link>
      ))}
    </nav>
  );
};

export default Nav;

MobileNav:

import React from "react";
import { Sheet, SheetTrigger, SheetContent, SheetClose } from "./ui/sheet";

import { AlignJustify } from "lucide-react";
import Logo from "./Logo";
import Socials from "./Socials";
import Nav from "./Nav";

const MobileNav = () => {
  return (
    <div>
      <Sheet>
        <SheetTrigger asChild>
          <AlignJustify className="cursor-pointer" />
        </SheetTrigger>
        <SheetContent>
          <div className="">
            <div className="">
              <Logo />
              <SheetClose asChild>
                <Nav />
              </SheetClose>
              <Socials containerStyles="flex gap-x-4" iconsStyles="text-2xl" />
            </div>
          </div>
        </SheetContent>
      </Sheet>
    </div>
  );
};

export default MobileNav;

Solution

  • Need to change few things in Nav components as follows :

    import { motion } from "framer-motion";
    import Link from "next/link";
    import { usePathname } from "next/navigation";
    import React from "react";
    import { SheetClose } from "./ui/sheet";
    
    interface Props {
      containerStyles?: string;
      linkStyles?: string;
      underlineStyles?: string;
    }
    
    const links = [
      { path: "/", name: "home" },
      { path: "/projects", name: "my projects" },
      { path: "/contact", name: "contact" },
    ];
    
    const Nav = ({ containerStyles, linkStyles, underlineStyles, ...restProps }: Props) => {
      const pathName = usePathname();
    
      return (
        <nav className={`${containerStyles}`}>
          {links.map((link, index) => (
            <Link
              key={index}
              href={link.path}
              className={`capitalize ${linkStyles}`}
              {...restProps}
            >
              {link.path === pathName && (
                <motion.span
                  initial={{ y: "-100%" }}
                  animate={{ y: 0 }}
                  transition={{ type: "tween" }}
                  layoutId="underline"
                  className={`${underlineStyles}`}
                />
              )}
              {link.name}
            </Link>
          ))}
        </nav>
      );
    };
    
    export default Nav;
    

    Changes:

    For more details please check Radix docs