컴포넌트

Navigation Menu

하위 링크가 있는 탐색 메뉴를 표시합니다.

설치

pnpm dlx ply-ui add navigation-menu icon

공통 설치 설정을 먼저 적용합니다.

사용법

Content 안에 Link를 두고, 공유 Portal/Viewport에서 펼친 내용을 표시합니다.

단순한 세로 링크 목록에는 Sidebar/NavigationLink를 사용할 수 있습니다.

구성

구성 요소역할
Root탐색 메뉴 상태를 관리합니다.
List / Item메뉴 목록과 하나의 항목입니다.
Trigger하위 탐색 내용을 펼칩니다.
Content항목에 연결된 하위 탐색 내용입니다.
Link실제 이동할 주소를 가진 링크입니다.
Portal / Positioner / Popup하위 내용의 위치와 표면을 구성합니다.

구현 코드

components/ui/navigation-menu.tsx
navigation-menu.tsx
"use client";

import type { ComponentProps } from "react";
import { NavigationMenu as Primitive } from "@base-ui/react/navigation-menu";
import { withClassName } from "../../lib/cx";
import "./navigation-menu.css";

// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function NavigationMenuRoot({
  className,
  ...props
}: ComponentProps<typeof Primitive.Root>) {
  return (
    <Primitive.Root
      {...props}
      className={withClassName("rbx-navigation-menu", className)}
    />
  );
}

function NavigationMenuList({
  className,
  ...props
}: ComponentProps<typeof Primitive.List>) {
  return (
    <Primitive.List
      {...props}
      className={withClassName("rbx-nav-list", className)}
    />
  );
}

function NavigationMenuTrigger({
  className,
  ...props
}: ComponentProps<typeof Primitive.Trigger>) {
  return (
    <Primitive.Trigger
      {...props}
      className={withClassName("rbx-button", className)}
    />
  );
}

function NavigationMenuLink({
  className,
  ...props
}: ComponentProps<typeof Primitive.Link>) {
  return (
    <Primitive.Link
      {...props}
      className={withClassName("rbx-nav-link", className)}
    />
  );
}

function NavigationMenuContent({
  className,
  ...props
}: ComponentProps<typeof Primitive.Content>) {
  return (
    <Primitive.Content
      {...props}
      className={withClassName("rbx-nav-content", className)}
    />
  );
}

function NavigationMenuPopup({
  className,
  ...props
}: ComponentProps<typeof Primitive.Popup>) {
  return (
    <Primitive.Popup
      {...props}
      className={withClassName("rbx-popup", className)}
    />
  );
}

function NavigationMenuPositioner({
  className,
  ...props
}: ComponentProps<typeof Primitive.Positioner>) {
  return (
    <Primitive.Positioner
      {...props}
      className={withClassName("rbx-positioner", className)}
    />
  );
}

// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const NavigationMenu = {
  ...Primitive,
  Root: NavigationMenuRoot,
  List: NavigationMenuList,
  Trigger: NavigationMenuTrigger,
  Link: NavigationMenuLink,
  Content: NavigationMenuContent,
  Popup: NavigationMenuPopup,
  Positioner: NavigationMenuPositioner,
};
components/ui/navigation-menu.css
navigation-menu.css
@import "./button.css";
/* NavigationMenu: 공통 구조는 theme.css, 컴포넌트 전용 조정은 아래에 작성합니다. */
.rbx-nav-list {
  display: flex;
  list-style: none;
  gap: 8px;
  padding: 0;
  margin: 0;
}
.rbx-nav-content {
  padding: 16px;
  display: grid;
  gap: 12px;
}

/* 링크를 버튼 표면으로 합성할 때 전경도 같은 action 역할을 사용합니다. */
.rbx-nav-link.rbx-button {
  color: var(--rbx-color-action-standard-foreground);
}

목차