Propel

Navigation Menu

A horizontal row of triggers and links that open portaled content panels for site navigation.

Basic

Show code
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuContentList,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkDescription,
  NavigationMenuLinkTitle,
  NavigationMenuList,
  NavigationMenuPanel,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@makeplane/propel/components/navigation-menu";

const PRODUCT_LINKS = [
  { href: "#issues", title: "Issues", description: "Track work items across projects." },
  { href: "#cycles", title: "Cycles", description: "Time-boxed sprints for your team." },
  { href: "#modules", title: "Modules", description: "Group related work into modules." },
  { href: "#pages", title: "Pages", description: "Rich documents that live with your work." },
];

const RESOURCE_LINKS = [
  { href: "#docs", title: "Documentation", description: "Guides and API references." },
  { href: "#changelog", title: "Changelog", description: "What shipped recently." },
];

export default function BasicDemo() {
  return (
    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger label="Product" />
          <NavigationMenuContent>
            <NavigationMenuContentList>
              {PRODUCT_LINKS.map((item) => (
                <li key={item.href}>
                  <NavigationMenuLink href={item.href} presentation="card">
                    <NavigationMenuLinkTitle>{item.title}</NavigationMenuLinkTitle>
                    <NavigationMenuLinkDescription>
                      {item.description}
                    </NavigationMenuLinkDescription>
                  </NavigationMenuLink>
                </li>
              ))}
            </NavigationMenuContentList>
          </NavigationMenuContent>
        </NavigationMenuItem>

        <NavigationMenuItem>
          <NavigationMenuTrigger label="Resources" />
          <NavigationMenuContent>
            <NavigationMenuContentList>
              {RESOURCE_LINKS.map((item) => (
                <li key={item.href}>
                  <NavigationMenuLink href={item.href} presentation="card">
                    <NavigationMenuLinkTitle>{item.title}</NavigationMenuLinkTitle>
                    <NavigationMenuLinkDescription>
                      {item.description}
                    </NavigationMenuLinkDescription>
                  </NavigationMenuLink>
                </li>
              ))}
            </NavigationMenuContentList>
          </NavigationMenuContent>
        </NavigationMenuItem>

        <NavigationMenuItem>
          <NavigationMenuLink href="#pricing" presentation="item">
            Pricing
          </NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>

      <NavigationMenuPanel>
        <NavigationMenuViewport />
      </NavigationMenuPanel>
    </NavigationMenu>
  );
}

Presentations

A link’s presentation sets its shape: item is a top-level pill beside the triggers, while card stacks a title over an optional description inside a content panel.

Show code
import {
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkDescription,
  NavigationMenuLinkTitle,
  NavigationMenuList,
} from "@makeplane/propel/components/navigation-menu";

export default function PresentationsDemo() {
  return (
    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuLink href="#pricing" presentation="item">
            Pricing
          </NavigationMenuLink>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="#docs" presentation="card">
            <NavigationMenuLinkTitle>Documentation</NavigationMenuLinkTitle>
            <NavigationMenuLinkDescription>
              Guides and API references.
            </NavigationMenuLinkDescription>
          </NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}

Large content

Cap the content region’s height and wrap the link list in a ScrollArea so the panel keeps a stable size while long menus scroll.

Show code
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuContentList,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkTitle,
  NavigationMenuList,
  NavigationMenuPanel,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@makeplane/propel/components/navigation-menu";
import { ScrollArea } from "@makeplane/propel/components/scroll-area";

const PROJECT_LINKS = Array.from({ length: 24 }, (_, index) => ({
  href: `#project-${index + 1}`,
  title: `Project ${index + 1}`,
}));

export default function LargeContentDemo() {
  return (
    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger label="Projects" />
          <NavigationMenuContent>
            <div className="flex h-72 flex-col">
              <ScrollArea orientation="vertical" visibility="auto" magnitude="thin">
                <NavigationMenuContentList>
                  {PROJECT_LINKS.map((item) => (
                    <li key={item.href}>
                      <NavigationMenuLink href={item.href} presentation="card">
                        <NavigationMenuLinkTitle>{item.title}</NavigationMenuLinkTitle>
                      </NavigationMenuLink>
                    </li>
                  ))}
                </NavigationMenuContentList>
              </ScrollArea>
            </div>
          </NavigationMenuContent>
        </NavigationMenuItem>

        <NavigationMenuItem>
          <NavigationMenuLink href="#pricing" presentation="item">
            Pricing
          </NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>

      <NavigationMenuPanel>
        <NavigationMenuViewport />
      </NavigationMenuPanel>
    </NavigationMenu>
  );
}

Installation

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuContentList,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuLinkDescription,
  NavigationMenuLinkTitle,
  NavigationMenuList,
  NavigationMenuPanel,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@makeplane/propel/components/navigation-menu";

Props

NavigationMenu

PropTypeRequiredDescription
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, NavigationMenuRootState>NoAllows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.

NavigationMenuTrigger

PropTypeRequiredDescription
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, NavigationMenuTriggerState>NoAllows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
iconReactNodeNoReplaces the default disclosure caret (a down chevron) in the trigger's `Icon` slot.
labelstringYesVisible trigger label.