Menu
A menu surface anchored to whatever invoker opens it, riding the same native Popover API Popover does, sized to its own content and padded around a compact stack of Menu.Item rows, Menu.Separator dividers.
View code
<Button commandfor="issue-menu" command="toggle-popover" variant="outline">
Issue actions
<ChevronDownIcon />
</Button>
<Menu id="issue-menu" aria-label="Issue actions" placement="bottom" mix={[menuKeys()]}>
<Section aria-labelledby="issue-menu-edit">
<Header id="issue-menu-edit">Edit</Header>
<Menu.Item href="/issues/482/edit">
<PencilIcon />
<span mix={[grow()]}>Rename</span>
<Keyboard>R</Keyboard>
</Menu.Item>
<Menu.Item>
<UserPlusIcon />
<span mix={[grow()]}>Assign to teammate</span>
<Keyboard>A</Keyboard>
</Menu.Item>
</Section>
<Menu.Separator />
<Section aria-labelledby="issue-menu-share">
<Header id="issue-menu-share">Share</Header>
<Menu.Item>
<CopyIcon />
<span mix={[grow()]}>Copy link</span>
<Keyboard>⌘C</Keyboard>
</Menu.Item>
<Menu.Item href="/issues/482" target="_blank" rel="noreferrer">
<ExternalLinkIcon />
<span mix={[grow()]}>Open in new tab</span>
</Menu.Item>
<Menu.Item disabled>
<ShareIcon />
<span mix={[grow()]}>Share externally</span>
</Menu.Item>
</Section>
<Menu.Separator />
<Menu.Item danger>
<Trash2Icon />
<span mix={[grow()]}>Delete issue</span>
<Keyboard>⌫</Keyboard>
</Menu.Item>
</Menu>Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/uiimport "@sdxc/ui/theme.css";Usage
import { Menu } from "@sdxc/ui";Renders the menu's own host: a Popover defaulting to
"bottom-start" placement and "menu" role, sized to its content. Point a
row's commandfor at another <Menu>'s id to open it as a nested menu.
Composition
The parts the component publishes, each a static property of the host.
MenuMenu.ItemRenders a native<a>whenhrefis set, else a<button>, defaultingroleto"menuitem"; only omitting or neutralizinghrefstops the<a>variant's navigation, sincearia-disabledmutes it visually only.Menu.SeparatorRenders a hairline divider between two runs of Menu.Items: the shared Separator component with the small block-axis margin a menu's compact rows need on either side of it.
Examples
<Menu id="row-menu" placement="left-start" aria-label={t("table.rowActions")}>
<Section aria-labelledby="row-menu-view-heading">
<Header id="row-menu-view-heading">{t("menu.view")}</Header>
<Menu.Item href={viewUrl}>{t("actions.view")}</Menu.Item>
<Menu.Item href={editUrl}>{t("actions.edit")}</Menu.Item>
</Section>
<Menu.Separator />
<Menu.Item danger commandfor="confirm-delete" command="show-modal">{t("actions.delete")}</Menu.Item>
</Menu>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
| Prop | Type | Description |
|---|---|---|
children | RemixNode | The menu's rows: Menu.Item, Menu.Separator, or a Section/Header pair grouping related items together. |
Also accepts everything in Popover.Props.
Menu.Item
| Prop | Type | Description |
|---|---|---|
href? | string | Destination the row navigates to. Renders the row as a native <a> instead of a <button> when set. |
target? | TagProps<"a">["target"] | target for the link variant, applied only once href is set. |
rel? | TagProps<"a">["rel"] | rel for the link variant, applied only once href is set. |
danger? | boolean | Styles the row in the semantic danger tone, for a destructive action like deleting a resource. |
mix? | MixinDescriptor<HTMLAnchorElement | HTMLButtonElement, any, ElementProps>[] | Extra mixin(s) applied to the row's host element, whichever of <a>/<button> it renders as depending on href. |
Also accepts everything in TagProps<"button">.
Menu.Separator
Also accepts everything in Separator.Props.