Standard duskmoon implemented 10 demos

Menu

Menu renders structured navigation or action lists.

Import @duskmoon-dev/components/menu
11 API sections
40 documented props
8 behavior scenarios
Key API
itemsselectedKeysdefaultSelectedKeysopenKeysdefaultOpenKeysmode

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

Stylesheet Import @duskmoon-dev/components/styles.css once in the app or docs shell.
State Start with default props for static examples, then switch to controlled props when state must be shared.
Theme The preview inherits the active DuskMoon data-theme value from the docs layout.

Features

Wayfinding

Covers the route, section, step, or action-list patterns that help users move through an interface.

Current state

Shows selected, active, open, or current props where the component exposes them.

Primary API surface

Menu is most often configured through `items`, `selectedKeys`, `defaultSelectedKeys`, `openKeys`.

Covered behavior

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.

Preview

Basic usage

authored

Import the component stylesheet and Menu from its package subpath, then render it with the core props.

Source
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" }
  ]}
/>);
}
Preview

Renders items with DuskMoon menu classes

test-backed

Menu scenario from the component test coverage: renders items with duskmoon menu classes.

Source
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" }
  ]}
/>);
}
Preview

Supports default selected keys and selection callbacks

test-backed

Menu scenario from the component test coverage: supports default selected keys and selection callbacks.

Source
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" }
  ]}
/>);
}
Preview

Supports submenu open state

test-backed

Menu scenario from the component test coverage: supports submenu open state.

Source
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" }
  ]}
/>);
}
Preview

Supports controlled selected keys

test-backed

Menu scenario from the component test coverage: supports controlled selected keys.

Source
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" }
  ]}
/>);
}
Preview

Supports multiple deselect

test-backed

Menu scenario from the component test coverage: supports multiple deselect.

Source
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" }
  ]}
/>);
}
Preview

Applies mode, theme, size, and disabled classes

test-backed

Menu scenario from the component test coverage: applies mode, theme, size, and disabled classes.

Source
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" }
  ]}
/>);
}
Preview

Exposes static child components

test-backed

Menu scenario from the component test coverage: exposes static child components.

Source
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" }
  ]}
/>);
}
Preview

Forwards root ref

test-backed

Menu scenario from the component test coverage: forwards root ref.

Source
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" }
  ]}
/>);
}
Preview
Sunshine Theme
Moonlight Theme

Theme aware

authored

Docs previews inherit the DuskMoon data-theme value. Use the header switch to compare light and dark rendering.

Source
<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.

Types: packages/components/src/components/menu/Menu.types.ts Scenarios: packages/components/src/components/menu/Menu.test.tsx
MenuProps interface extends Omit< ComponentProps<"ul">, "onClick" | "onSelect" >
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.
MenuItemType interface
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.
MenuClickInfo interface
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.
MenuItemProps interface extends ComponentProps<"li">
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.
MenuItemGroupProps interface extends Omit< ComponentProps<"li">, "title" >
Prop Type Required Description
title ReactNode No title configures Menu.
MenuComponent interface extends ForwardRefExoticComponent< MenuProps & RefAttributes<HTMLUListElement> >
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.
MenuKey type
string | number
MenuMode type
"vertical" | "horizontal" | "inline"
MenuTheme type
"light" | "dark"
MenuSize type
"sm" | "md" | "lg"
MenuDividerProps type
ComponentProps<"li">