import { ListIcon } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@/shim-ui/button";
import { Menu, MenuItem, MenuSeparator, MenuTrigger } from "@/shim-ui/menu";
export default () => (
<MenuTrigger>
<Button aria-label="Menu">
<ListIcon size={16} />
</Button>
<Menu>
<MenuItem>Edit</MenuItem>
<MenuItem>Duplicate</MenuItem>
<MenuSeparator />
<MenuItem intent="danger">Delete</MenuItem>
</Menu>
</MenuTrigger>
);Install
Use the CLI or copy the source code manually.
Command
Source code
pnpm dlx @kkga/shim add menuSize
Set the overall menu dimensions with the size prop.
import { ListIcon } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@/shim-ui/button";
import { Menu, MenuItem, MenuSeparator, MenuTrigger } from "@/shim-ui/menu";
export default () =>
([1, 2, 3, 4] as const).map((size) => (
<MenuTrigger key={size}>
<Button aria-label="Menu" size={size}>
<ListIcon size={"1em"} />
</Button>
<Menu size={size}>
<MenuItem>Edit</MenuItem>
<MenuItem>Duplicate</MenuItem>
<MenuSeparator />
<MenuItem intent="danger">Delete</MenuItem>
</Menu>
</MenuTrigger>
));Sections
Group items with <MenuSection> and provide a heading via the title prop.
import { CaretDown } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@/shim-ui/button";
import { Menu, MenuItem, MenuSection, MenuTrigger } from "@/shim-ui/menu";
export default () => (
<MenuTrigger>
<Button aria-label="Pick file">
Pick file
<CaretDown size={12} weight="bold" />
</Button>
<Menu>
<MenuSection title="Recent">
<MenuItem>File 1</MenuItem>
<MenuItem>File 2</MenuItem>
<MenuItem>File 3</MenuItem>
</MenuSection>
<MenuSection title="Favorites">
<MenuItem>File 4</MenuItem>
<MenuItem>File 5</MenuItem>
<MenuItem>File 6</MenuItem>
</MenuSection>
</Menu>
</MenuTrigger>
);Content
Menu follows the Collections API and supports both static and dynamic items.
Pass an items prop and a render function as children to render dynamic collections. The render function receives each item from items and should return a React element.
"use client";
import { CaretDownIcon } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@/shim-ui/button";
import { Menu, MenuItem, MenuTrigger } from "@/shim-ui/menu";
export default () => {
const items = [
{ id: 1, name: "New" },
{ id: 2, name: "Open" },
{ id: 3, name: "Close" },
{ id: 4, name: "Save" },
{ id: 5, name: "Duplicate" },
{ id: 6, name: "Rename" },
{ id: 7, name: "Move" },
];
return (
<MenuTrigger>
<Button aria-label="Menu">
Options
<CaretDownIcon size={12} weight="bold" />
</Button>
<Menu items={items}>{(item) => <MenuItem>{item.name}</MenuItem>}</Menu>
</MenuTrigger>
);
};Selection
Menu supports single, multiple, and uncontrolled selection modes. Enable selection by setting the selectionMode prop.
"use client";
import { CaretDown } from "@phosphor-icons/react/dist/ssr";
import { useState } from "react";
import type { Selection } from "react-aria-components";
import { Button } from "@/shim-ui/button";
import { Menu, MenuItem, MenuTrigger } from "@/shim-ui/menu";
export default () => {
const [align, setAlign] = useState<Selection>(new Set(["center"]));
const [views, setViews] = useState<Selection>(new Set(["sidebar"]));
return (
<div className="flex gap-2">
<MenuTrigger>
<Button aria-label="Align">
Align
<CaretDown size={12} weight="bold" />
</Button>
<Menu
onSelectionChange={setAlign}
selectedKeys={align}
selectionMode="single"
>
<MenuItem id="left">Left</MenuItem>
<MenuItem id="center">Center</MenuItem>
<MenuItem id="right">Right</MenuItem>
</Menu>
</MenuTrigger>
<MenuTrigger>
<Button aria-label="Views">
Views
<CaretDown size={12} weight="bold" />
</Button>
<Menu
onSelectionChange={setViews}
selectedKeys={views}
selectionMode="multiple"
>
<MenuItem id="sidebar">Sidebar</MenuItem>
<MenuItem id="toolbar">Toolbar</MenuItem>
<MenuItem id="inspector">Inspector</MenuItem>
</Menu>
</MenuTrigger>
</div>
);
};