A configuration-driven vertical navigation menu (sidebar). It renders a tree of links/buttons from a configuration array, resolves the active branch from the current route, and supports a collapsed (icons-only) mode and popover submenus.
Use Menu for app navigation where items are known up front and active state follows the route. For a contextual action menu opened from a trigger, use Dropdown with a headless layer, or Popover for a custom floating panel.
Collapsed and popover submenus are rendered with the internal Popover component.
There is no @uxf/form twin.
import { Menu } from "@uxf/ui/menu";
<Menu
configuration={[
{ label: "Home", icon: "eye", href: "/", routeMatcher: (pathname) => pathname === "/" },
{
label: "Reports",
icon: "file",
children: [{ label: "Monthly", href: "/reports/monthly", icon: "copy" }],
},
{ label: "Sign out", icon: "file", onClick: () => signOut() },
]}
router={{ pathname: "/", pathParams: {} }}
/>;
MenuConfiguration / MenuItemConfiguration are not re-exported from the package index; type an inline array against MenuProps["configuration"], or deep-import from @uxf/ui/menu/menu / @uxf/ui/menu/types.
Pass the current route into router. Menu calls each item's routeMatcher(pathname, pathParams) and marks an item active when it matches (a parent is active when any descendant is).
// app directory
import { usePathname } from "next/navigation";
import { usePageParams } from "@app-routes";
const pathname = usePathname();
const pathParams = usePageParams();
<Menu configuration={configuration} router={{ pathname, pathParams }} />;
// pages directory
import { useRouter } from "next/router";
const router = useRouter();
<Menu configuration={configuration} router={router} />;
| Prop | Type | Default | Description |
|---|---|---|---|
configuration | MenuItemConfiguration[] | — | Required. Menu tree (see item shape below). |
router | { pathname: string | null; pathParams?: RouterPathParams | null } | — | Required. Current route, used to resolve the active item. |
isCollapsed | boolean | false | Collapse to icons only; labels and right elements are hidden and submenus open in a hover popover. |
isPopoverEnabled | boolean | false | Render submenus in a hover popover instead of expanding inline. |
className | string | — | Extra class on the root uxf-menu element. |
MenuItemConfiguration| Field | Type | Description |
|---|---|---|
label | string | Required. Item text (also used as title). |
icon | IconName | Leading icon. |
href | string | Renders the item as a link. |
as | "a" | NextLink | Link component used when href is set (defaults to <a>). |
onClick | () => void | Renders the item as a <button>; on an item with children, clicking toggles expansion when no onClick is given. |
children | MenuItemConfiguration[] | Submenu items. |
routeMatcher | (pathname: string, pathParams?: RouterPathParams) => boolean | Returns true when the item is active for the current route. |
badge | ReactElement | Element rendered on the right (a dot indicator when collapsed). |
href renders a link (as/NextLink or <a>); with onClick and no children it renders a <button>; with children it toggles a submenu; with none of these it renders a non-interactive <div>.routeMatcher matches are marked active, and ancestors of an active item are active too. Branches start expanded when active (unless collapsed).isCollapsed or isPopoverEnabled mode, submenus appear in a right-start hover popover.Import the component stylesheet once in your global CSS:
@import url("@uxf/ui/css/menu.css");
Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.