컴포넌트
Menu
버튼을 눌러 작업 목록을 엽니다.
설치
pnpm dlx ply-ui add menu icon공통 설치 설정을 먼저 적용합니다.
사용법
버튼을 눌러 작업 목록을 열 때 사용합니다. Item.onClick에 작업을 연결합니다. 값을 선택하는 입력은 Select를 사용합니다.
구성
| 구성 요소 | 역할 |
|---|---|
Root | 메뉴의 열림 상태를 관리합니다. |
Trigger | 메뉴를 여는 버튼입니다. |
Portal / Positioner | 메뉴를 별도 영역에 렌더하고 버튼을 기준으로 배치합니다. |
Popup | 목록의 표면입니다. size의 기본값은 md입니다. |
Item | 하나의 작업입니다. onClick으로 동작을 연결합니다. |
Group / GroupLabel / Separator | 관련 작업을 묶거나 구분합니다. |
SubmenuRoot / SubmenuTrigger | 하위 메뉴의 상태와 여는 항목을 구성합니다. |
CheckboxItem / CheckboxItemIndicator | 서로 독립적인 켜짐·꺼짐 항목과 선택 표시입니다. |
RadioGroup / RadioItem / RadioItemIndicator | 여러 값 중 하나를 선택하는 항목과 선택 표시입니다. |
크기 XS
Popup size="xs"로 목록 항목의 글자 크기와 여백을 지정합니다.
크기 SM
Popup size="sm"로 목록 항목의 글자 크기와 여백을 지정합니다.
크기 MD
Popup size="md"로 목록 항목의 글자 크기와 여백을 지정합니다. Menu의 기본값입니다.
크기 LG
Popup size="lg"로 목록 항목의 글자 크기와 여백을 지정합니다.
체크 항목
CheckboxItem은 켜짐과 꺼짐을 전환합니다. checked와 onCheckedChange를 연결합니다.
비활성 항목
작업 하나만 사용할 수 없을 때는 해당 Item에 disabled를 지정합니다.
하나의 설정 선택
RadioGroup이 선택값을 관리합니다. 그룹 안의 RadioItem마다 고유한 값을 지정합니다.
하위 메뉴
SubmenuRoot 안에 SubmenuTrigger와 하위 Popup을 구성합니다. 오른쪽 방향키로 하위 메뉴에 들어갈 수 있습니다.
속성
이 프로젝트에서 추가하거나 제한한 속성입니다.
Popup
구현 코드
components/ui/menu.tsx
"use client";
import type { ComponentProps } from "react";
import { Menu as Primitive } from "@base-ui/react/menu";
import { withClassName } from "../../lib/cx";
import "./menu.css";
// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function MenuTrigger({
className,
...props
}: ComponentProps<typeof Primitive.Trigger>) {
return (
<Primitive.Trigger
{...props}
className={withClassName("rbx-button", className)}
/>
);
}
export type MenuPopupProps = ComponentProps<typeof Primitive.Popup> & {
/** 목록 항목의 글자 크기와 여백입니다. @defaultValue "md" */
size?: "xs" | "sm" | "md" | "lg";
};
function MenuPopup({ size = "md", className, ...props }: MenuPopupProps) {
return (
<Primitive.Popup
{...props}
data-size={size}
className={withClassName("rbx-popup", className)}
/>
);
}
function MenuPositioner({
className,
...props
}: ComponentProps<typeof Primitive.Positioner>) {
return (
<Primitive.Positioner
{...props}
className={withClassName("rbx-positioner", className)}
/>
);
}
function MenuItem({
className,
...props
}: ComponentProps<typeof Primitive.Item>) {
return (
<Primitive.Item
{...props}
className={withClassName("rbx-option", className)}
/>
);
}
function MenuSubmenuTrigger({
className,
...props
}: ComponentProps<typeof Primitive.SubmenuTrigger>) {
return (
<Primitive.SubmenuTrigger
{...props}
className={withClassName("rbx-option", className)}
/>
);
}
function MenuGroupLabel({
className,
...props
}: ComponentProps<typeof Primitive.GroupLabel>) {
return (
<Primitive.GroupLabel
{...props}
className={withClassName("rbx-group-label", className)}
/>
);
}
function MenuCheckboxItem({
className,
...props
}: ComponentProps<typeof Primitive.CheckboxItem>) {
return (
<Primitive.CheckboxItem
{...props}
className={withClassName("rbx-option", className)}
/>
);
}
function MenuCheckboxItemIndicator({
className,
...props
}: ComponentProps<typeof Primitive.CheckboxItemIndicator>) {
return (
<Primitive.CheckboxItemIndicator
{...props}
className={withClassName("rbx-option-indicator", className)}
/>
);
}
function MenuRadioItem({
className,
...props
}: ComponentProps<typeof Primitive.RadioItem>) {
return (
<Primitive.RadioItem
{...props}
className={withClassName("rbx-option", className)}
/>
);
}
function MenuRadioItemIndicator({
className,
...props
}: ComponentProps<typeof Primitive.RadioItemIndicator>) {
return (
<Primitive.RadioItemIndicator
{...props}
className={withClassName("rbx-option-indicator", className)}
/>
);
}
function MenuSeparator({
className,
...props
}: ComponentProps<typeof Primitive.Separator>) {
return (
<Primitive.Separator
{...props}
className={withClassName("rbx-separator", className)}
/>
);
}
// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Menu = {
...Primitive,
Separator: MenuSeparator,
Trigger: MenuTrigger,
Popup: MenuPopup,
Positioner: MenuPositioner,
Item: MenuItem,
SubmenuTrigger: MenuSubmenuTrigger,
GroupLabel: MenuGroupLabel,
CheckboxItem: MenuCheckboxItem,
CheckboxItemIndicator: MenuCheckboxItemIndicator,
RadioItem: MenuRadioItem,
RadioItemIndicator: MenuRadioItemIndicator,
};
components/ui/menu.css
@import "./button.css";
/* Menu: 공통 구조는 theme.css, 컴포넌트 전용 조정은 아래에 작성합니다. */