Primitives
Context menu
Right-click or long-press. The same items and looks as DropdownMenu; submenus, checks, a danger item.
Right-click a row (long-press on a phone).
"use client";
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuLabel,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
toast,
} from "@waveinno/ui";
import { Copy, Download, Pencil, Trash2 } from "lucide-react";
import * as React from "react";
export default function ContextMenuDemo() {
const [pinned, setPinned] = React.useState(true);
const rows = ["DHA-GA 12-3456", "DHA-KHA 45-1029", "CTG-GA 11-8890"];
return (
<div className="space-y-2">
<p className="text-[13px] text-muted">Right-click a row (long-press on a phone).</p>
{rows.map((r) => (
<ContextMenu key={r}>
<ContextMenuTrigger asChild>
<div className="flex cursor-context-menu items-center justify-between rounded-[12px] border border-border bg-raised px-4 py-3 text-[13.5px] transition-colors data-[state=open]:border-primary data-[state=open]:bg-primary-subtle/40">
<span className="font-mono font-semibold text-text">{r}</span>
<span className="text-muted">Level B · 2 h 10 m</span>
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuLabel>{r}</ContextMenuLabel>
<ContextMenuItem icon={<Pencil />} shortcut="E" onSelect={() => toast(`Editing ${r}`)}>
Edit session
</ContextMenuItem>
<ContextMenuItem icon={<Copy />} shortcut="⌘C" onSelect={() => (void navigator.clipboard?.writeText(r), toast.success("Plate copied"))}>
Copy plate
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>
<Download /> Export
</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>As PDF receipt</ContextMenuItem>
<ContextMenuItem>As Excel row</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
<ContextMenuCheckboxItem checked={pinned} onCheckedChange={setPinned}>
Pin to the top
</ContextMenuCheckboxItem>
<ContextMenuSeparator />
<ContextMenuItem danger icon={<Trash2 />} description="The fee so far is kept." onSelect={() => toast.error(`${r} ended`)}>
End session
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
))}
</div>
);
}Import#
Everything comes from the package root. The example above uses:
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuLabel,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
toast,
} from "@waveinno/ui";Props#
Read from the source of this version, so they match the code exactly.
<ContextMenuCheckboxItem>
src/components/ui/context-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.CheckboxItem> (passed through).
<ContextMenuContent>
src/components/ui/context-menu.tsx| Prop | Type | Default | Description |
|---|---|---|---|
variant | MenuVariant | "default" |
Also takes ComponentPropsWithoutRef<typeof Primitive.Content>.
<ContextMenuItem>
src/components/ui/context-menu.tsx| Prop | Type | Default | Description |
|---|---|---|---|
danger | boolean | — | |
icon | React.ReactNode | — | |
description | React.ReactNode | — | |
shortcut | string | — |
Also takes ComponentPropsWithoutRef<typeof Primitive.Item>.
<ContextMenuLabel>
src/components/ui/context-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.Label> (passed through).
<ContextMenuSeparator>
src/components/ui/context-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.Separator> (passed through).
<ContextMenuSubContent>
src/components/ui/context-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.SubContent> (passed through).
<ContextMenuSubTrigger>
src/components/ui/context-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.SubTrigger> (passed through).
Install#
If the project does not have the package yet, add it, then follow the setup for Next.js or Vite once.
$ npm install @waveinno/ui