Menu
Menu renders structured navigation or action lists.
@duskmoon-dev/components/menu Usage
When to use
- Use it when users need to move between sections, pages, steps, or contextual actions.
- Expose current and disabled state so navigation remains clear to keyboard and screen-reader users.
Implementation notes
Features
Covers the route, section, step, or action-list patterns that help users move through an interface.
Shows selected, active, open, or current props where the component exposes them.
Menu is most often configured through `items`, `selectedKeys`, `defaultSelectedKeys`, `openKeys`.
Renders items with DuskMoon menu classes
Feature Demos
Feature demos are authored for the component page, then supplemented with behavior scenarios from the component test coverage.
Basic usage
Import the component stylesheet and Menu from its package subpath, then render it with the core props.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function Example() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Renders items with DuskMoon menu classes
test-backedMenu scenario from the component test coverage: renders items with duskmoon menu classes.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuRendersItemsWithDuskMoonDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Supports default selected keys and selection callbacks
test-backedMenu scenario from the component test coverage: supports default selected keys and selection callbacks.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuSupportsDefaultSelectedKeysDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Supports submenu open state
test-backedMenu scenario from the component test coverage: supports submenu open state.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuSupportsSubmenuOpenStateDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Supports controlled selected keys
test-backedMenu scenario from the component test coverage: supports controlled selected keys.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuSupportsControlledSelectedKeysDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Supports multiple deselect
test-backedMenu scenario from the component test coverage: supports multiple deselect.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuSupportsMultipleDeselectDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Applies mode, theme, size, and disabled classes
test-backedMenu scenario from the component test coverage: applies mode, theme, size, and disabled classes.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuAppliesModeThemeSizeDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Exposes static child components
test-backedMenu scenario from the component test coverage: exposes static child components.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuExposesStaticChildComponentsDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Forwards root ref
test-backedMenu scenario from the component test coverage: forwards root ref.
import "@duskmoon-dev/components/styles.css";
import { Menu } from "@duskmoon-dev/components/menu";
export function MenuForwardsRootRefDemo() {
return (<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>);
} Theme aware
Docs previews inherit the DuskMoon data-theme value. Use the header switch to compare light and dark rendering.
<div data-theme="sunshine">
<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>
</div>
<div data-theme="moonlight">
<Menu
defaultSelectedKeys={["overview"]}
defaultOpenKeys={["workspace"]}
items={[
{ key: "overview", label: "Overview", extra: "⌘1" },
{
key: "workspace",
label: "Workspace",
children: [
{ key: "tasks", label: "Tasks" },
{ key: "reports", label: "Reports" }
]
},
{ type: "divider" },
{ key: "settings", label: "Settings" }
]}
/>
</div> API
The API reference below lists every parsed exported type or interface for Menu. Start with `items`, `selectedKeys`, `defaultSelectedKeys`, `openKeys` for common usage.
packages/components/src/components/menu/Menu.types.ts
Scenarios: packages/components/src/components/menu/Menu.test.tsx | Prop | Type | Required | Description |
|---|---|---|---|
items | MenuItemType[] | No | items configures Menu. |
selectedKeys | MenuKey[] | No | selectedKeys configures Menu. |
defaultSelectedKeys | MenuKey[] | No | defaultSelectedKeys configures Menu. |
openKeys | MenuKey[] | No | openKeys configures Menu. |
defaultOpenKeys | MenuKey[] | No | defaultOpenKeys configures Menu. |
mode | MenuMode | No | mode configures Menu. |
theme | MenuTheme | No | theme configures Menu. |
size | MenuSize | No | size configures Menu. |
selectable | boolean | No | selectable configures Menu. |
multiple | boolean | No | multiple configures Menu. |
inlineCollapsed | boolean | No | inlineCollapsed configures Menu. |
disabled | boolean | No | disabled configures Menu. |
onClick | (info: MenuClickInfo) => void | No | onClick configures Menu. |
onSelect | (info: MenuClickInfo) => void | No | onSelect configures Menu. |
onDeselect | (info: MenuClickInfo) => void | No | onDeselect configures Menu. |
onOpenChange | (openKeys: string[]) => void | No | onOpenChange configures Menu. |
| Prop | Type | Required | Description |
|---|---|---|---|
key | MenuKey | No | key configures Menu. |
label | ReactNode | No | label configures Menu. |
title | ReactNode | No | title configures Menu. |
icon | ReactNode | No | icon configures Menu. |
extra | ReactNode | No | extra configures Menu. |
children | MenuItemType[] | No | children configures Menu. |
disabled | boolean | No | disabled configures Menu. |
danger | boolean | No | danger configures Menu. |
type | "item" | "group" | "divider" | No | type configures Menu. |
className | string | No | className configures Menu. |
| Prop | Type | Required | Description |
|---|---|---|---|
key | string | Yes | key configures Menu. |
keyPath | string[] | Yes | keyPath configures Menu. |
item | MenuItemType | Yes | item configures Menu. |
selectedKeys | string[] | Yes | selectedKeys configures Menu. |
domEvent | MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement> | Yes | domEvent configures Menu. |
| Prop | Type | Required | Description |
|---|---|---|---|
disabled | boolean | No | disabled configures Menu. |
danger | boolean | No | danger configures Menu. |
active | boolean | No | active configures Menu. |
icon | ReactNode | No | icon configures Menu. |
extra | ReactNode | No | extra configures Menu. |
| Prop | Type | Required | Description |
|---|---|---|---|
title | ReactNode | No | title configures Menu. |
| Prop | Type | Required | Description |
|---|---|---|---|
Item | ForwardRefExoticComponent<MenuItemProps & RefAttributes<HTMLLIElement>> | Yes | Item configures Menu. |
Divider | ForwardRefExoticComponent< | Yes | Divider configures Menu. |
ItemGroup | ForwardRefExoticComponent< | Yes | ItemGroup configures Menu. |
string | number "vertical" | "horizontal" | "inline" "light" | "dark" "sm" | "md" | "lg" ComponentProps<"li">