Navigation Menu
trovecn/navigation-menuFreeComponent
Mega-menu nav with a shared viewport that resizes between preview panels.
Install it
npx shadcn@latest add https://trovecn.dev/r/navigation-menu.jsonSource
1"use client";23import {4 Children,5 cloneElement,6 createContext,7 isValidElement,8 useContext,9 useEffect,10 useMemo,11 useRef,12 type ReactElement,13 type ReactNode,14} from "react";15import { NavigationMenu as NavigationMenuPrimitive } from "@base-ui/react/navigation-menu";16import { ChevronDownIcon } from "lucide-react";1718import { cn } from "@/lib/utils";19import { ProximityHoverPill } from "@/components/ui/proximity-hover-pill";20import { useProximityHover, type ItemRect } from "@/hooks/use-proximity-hover";2122const viewportTransition =23 "transition-[top,left,right,bottom,width,height] delay-50 duration-200 ease-out data-ending-style:delay-0 data-ending-style:duration-150 data-instant:transition-none";24const popupTransition =25 "transition-[opacity,transform,width,height] delay-50 duration-200 ease-out data-ending-style:delay-0 data-ending-style:duration-150";26const contentTransition =27 "transition-[opacity,transform] duration-200 ease-out data-ending-style:duration-150";2829interface NavigationMenuProximityContextValue {30 registerItem: (index: number, element: HTMLElement | null) => void;31}3233const NavigationMenuProximityContext = createContext<NavigationMenuProximityContextValue | null>(34 null,35);3637type NavigationMenuIndexProp = { _index?: number };3839function indexNavigationMenuItems(children: ReactNode): ReactNode {40 let index = -1;41 return Children.map(children, (child) => {42 if (!isValidElement(child) || child.type !== NavigationMenuItem) return child;43 index += 1;44 return cloneElement(child as ReactElement<NavigationMenuIndexProp>, { _index: index });45 });46}4748function NavigationMenu({49 align = "start",50 className,51 children,52 ...props53}: NavigationMenuPrimitive.Root.Props & Pick<NavigationMenuPrimitive.Positioner.Props, "align">) {54 return (55 <NavigationMenuPrimitive.Root56 data-slot="navigation-menu"57 className={cn(58 "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",59 className,60 )}61 {...props}62 >63 {children}64 <NavigationMenuPositioner align={align} />65 </NavigationMenuPrimitive.Root>66 );67}6869function NavigationMenuList({ className, children, ...props }: NavigationMenuPrimitive.List.Props) {70 const containerRef = useRef<HTMLUListElement>(null);71 const { activeIndex, itemRects, handlers, registerItem, measureItems } = useProximityHover(72 containerRef,73 { axis: "x" },74 );7576 useEffect(() => {77 measureItems();78// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from trovecn
All 26 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | trovecn | Components | Free | 3 deps | |
| Agent Activityagent-activity | trovecn | Components | Free | 2 deps | |
| Approval Requestapproval-request | trovecn | Components | Free | 2 deps | |
| Buttonbutton | trovecn | Components | Free | 2 deps | |
| Checkboxcheckbox | trovecn | Components | Free | 2 deps | |
| Checkbox Groupcheckbox-group | trovecn | Components | Free | 2 deps | |
| Comboboxcombobox | trovecn | Components | Free | 3 deps | |
| Comparison Slidercomparison-slider | trovecn | Components | Free | 1 dep |
