ui icon indicating copy to clipboard operation
ui copied to clipboard

Navigation Menu Auto Resizing

Open jonwgeorge opened this issue 2 years ago • 5 comments

I am in the process of converting an internal tool over to use Shadcn UI. With the navigation menu I'm seeing the drop down resize itself until it disappears. I've checked all the tailwind classes trying to find the culprit and can't seem to determine a cause. Am I accidentally applying a class or a prop to cause this?

Screen Recording 2024-01-24 at 08 54 41

Here's the code.

"use client";

import * as React from "react";
import { cn } from "@/lib/utils";

import {
  NavigationMenu,
  NavigationMenuList,
  NavigationMenuItem,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
import Image from "next/image";
import Link from "next/link";
import logo from "@/public/logo.svg";
import {
  NavigationMenuContent,
  NavigationMenuLink,
  NavigationMenuTrigger,
} from "@radix-ui/react-navigation-menu";

import MaxWidthWrapper from "../MaxWidthcontainer";
import { useMsal } from "@azure/msal-react";

const tools: { title: string; href: string; description: string }[] = [
  {
    title: "Domain Tool",
    href: "/tools/domain",
    description: "Helper for looking up domain records such as A and MX",
  },
  {
    title: "Option 43 Helper",
    href: "/tools/opt43",
    description: "Generates Option 43 Strings for Sophos and other appliances",
  },
  {
    title: "Option 125 Helper",
    href: "/tools/opt125",
    description: "Generates Option 125 Strings for Mitel Phones",
  },
  {
    title: "SMDR Helper",
    href: "/tools/smdr",
    description: "Reads and converts SMDR logs to a human readable format",
  },
];

export default function Navigation() {
  const { accounts } = useMsal();

  return (
    <MaxWidthWrapper className="space-x-1 box-border shadow-md mt-2 mb-5 bg-white rounded-md">
      <NavigationMenu>
        <NavigationMenuList>
          <NavigationMenuItem>
            <Link href="/" legacyBehavior passHref>
              <NavigationMenuLink>
                <Image src={logo} alt="" width="70" />
              </NavigationMenuLink>
            </Link>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <Link href="/" legacyBehavior passHref>
              <NavigationMenuLink className={navigationMenuTriggerStyle()}>
                Dashboard
              </NavigationMenuLink>
            </Link>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuTrigger className={navigationMenuTriggerStyle()}>Tools</NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]">
                {tools.map((tool) => (
                  <ListItem
                    key={tool.title}
                    title={tool.title}
                    href={tool.href}
                  >
                    {tool.description}
                  </ListItem>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <Link href="/" legacyBehavior passHref>
              <NavigationMenuLink className={navigationMenuTriggerStyle()}>
              </NavigationMenuLink>
            </Link>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </MaxWidthWrapper>
  );
}

const ListItem = React.forwardRef<
  React.ElementRef<"a">,
  React.ComponentPropsWithoutRef<"a">
>(({ className, title, children, ...props }, ref) => {
  return (
    <li>
      <NavigationMenuLink asChild>
        <a
          ref={ref}
          className={cn(
            "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
            className
          )}
          {...props}
        >
          <div className="text-sm font-medium leading-none">{title}</div>
          <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
            {children}
          </p>
        </a>
      </NavigationMenuLink>
    </li>
  );
});
ListItem.displayName = "ListItem";

jonwgeorge avatar Jan 24 '24 15:01 jonwgeorge

Hi @jonwgeorge ,

Just tried your code and everything seems to be fine. Unfortunately, I'm not sure what's happening in <MaxWidthWrapper /> and I can't check the useMsal() hook. Try removing them and see if the problem persists.

iTsygancov avatar Jan 24 '24 15:01 iTsygancov

@iTsygancov <MaxWidthWrapper /> ensures all pages/views stay within our preferred screen size and useMsal() is authentication with our Azure backend. I had previously removed them and tested and it still has the same behavior. I was afraid this was something deeper. I'll keep poking around all the components on screen and see what I get. It's happening in all browsers on my test environment.

jonwgeorge avatar Jan 24 '24 15:01 jonwgeorge

@jonwgeorge If anything, I'd be happy to help =) Good luck!

iTsygancov avatar Jan 24 '24 15:01 iTsygancov

@iTsygancov does this give any context? This is the resulting HTML after the menu has completely resized itself. I'm not seeing an issue that pops out at me.

<div class="absolute left-0 top-full flex justify-center">
  <div
    data-state="open"
    data-orientation="horizontal"
    class="origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]"
    style="
      --radix-navigation-menu-viewport-width: 0px;
      --radix-navigation-menu-viewport-height: 204px;
    "
  >
    <div
      id="radix-:R1kq:-content-radix-:R3dkq:"
      aria-labelledby="radix-:R1kq:-trigger-radix-:R3dkq:"
      data-orientation="horizontal"
      dir="ltr"
    >
      <ul
        class="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"
      >
        <li>
          <a
            class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
            href="/tools/domain"
            data-radix-collection-item=""
            ><div class="text-sm font-medium leading-none">Domain Tool</div>
            <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
              Helper for looking up domain records such as A and MX
            </p></a
          >
        </li>
        <li>
          <a
            class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
            href="/tools/opt43"
            data-radix-collection-item=""
            ><div class="text-sm font-medium leading-none">
              Option 43 Helper
            </div>
            <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
              Generates Option 43 Strings for Sophos and other appliances
            </p></a
          >
        </li>
        <li>
          <a
            class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
            href="/tools/opt125"
            data-radix-collection-item=""
            ><div class="text-sm font-medium leading-none">
              Option 125 Helper
            </div>
            <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
              Generates Option 125 Strings for Mitel Phones
            </p></a
          >
        </li>
        <li>
          <a
            class="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
            href="/tools/smdr"
            data-radix-collection-item=""
            ><div class="text-sm font-medium leading-none">SMDR Helper</div>
            <p class="line-clamp-2 text-sm leading-snug text-muted-foreground">
              Reads and converts SMDR logs to a human readable format
            </p></a
          >
        </li>
      </ul>
    </div>
  </div>
</div>

jonwgeorge avatar Jan 24 '24 16:01 jonwgeorge

@jonwgeorge I was able to reproduce your problem. You are using some of the components that are imported directly from radix-ui library and mix them with components from shadcn-ui.

To fix your issue you can remove this import:

import {
  NavigationMenuContent,
  NavigationMenuLink,
  NavigationMenuTrigger
} from "@radix-ui/react-navigation-menu";

And update this import:

import {
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuList,
  NavigationMenuContent,
  NavigationMenuLink,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle
} from "@/components/ui/navigation-menu";

If you still want to use <NavigationMenuContent /> component directly from radix-ui library than you can add absolute class to it and your problem will be resolved.

I hope that helped =)

iTsygancov avatar Jan 25 '24 07:01 iTsygancov

@iTsygancov That was it! Thanks for the second pair of eyes!

jonwgeorge avatar Jan 29 '24 02:01 jonwgeorge