Menu

Context menu for right-click actions.

import { Menu } from "ui-lab-components";
 
export function Example() {
  return (
    <Menu>
      <Menu.Trigger>Right click here</Menu.Trigger>
      <Menu.Content>
        <Menu.Item>Copy</Menu.Item>
        <Menu.Item>Paste</Menu.Item>
        <Menu.Item disabled>Cut</Menu.Item>
      </Menu.Content>
    </Menu>
  );
}

Basic Menu

A simple context menu triggered by right-click. Use this to provide quick access to common actions and context-specific commands.

import { Menu } from 'ui-lab-components';
 
export const metadata = {
  title: 'Basic Menu',
  description: 'A simple context menu triggered by right-click. Use this to provide quick access to common actions and context-specific commands.'
};
 
export default function Example() {
  return (
    <Menu>
      <Menu.Trigger className="flex items-center justify-center rounded-md border-2 border-dashed border-background-600 p-12 w-full cursor-context-menu select-none text-foreground-300 hover:border-background-500 transition-colors">
        Right click here
      </Menu.Trigger>
      <Menu.Content>
        <Menu.Item>Copy</Menu.Item>
        <Menu.Item>Paste</Menu.Item>
        <Menu.Item disabled>Cut</Menu.Item>
      </Menu.Content>
    </Menu>
  );
}
 

Nested Menu

Context menu with submenus for organizing related actions. Hover over items with arrows to reveal nested options.

import { Menu } from 'ui-lab-components';
 
export const metadata = {
  title: 'Nested Menu',
  description: 'Context menu with submenus for organizing related actions. Hover over items with arrows to reveal nested options.'
};
 
export default function Example() {
  return (
    <Menu>
      <Menu.Trigger className="flex items-center justify-center rounded-md border-2 border-dashed border-background-600 p-12 w-full cursor-context-menu select-none text-foreground-300 hover:border-background-500 transition-colors">
        Right click here
      </Menu.Trigger>
      <Menu.Content>
        <Menu.Item>New File</Menu.Item>
        <Menu.Item>New Folder</Menu.Item>
        <Menu.Separator />
        <Menu.Sub>
          <Menu.SubTrigger>Open with...</Menu.SubTrigger>
          <Menu.SubContent>
            <Menu.Item>VS Code</Menu.Item>
            <Menu.Item>Sublime Text</Menu.Item>
            <Menu.Item>Vim</Menu.Item>
            <Menu.Separator />
            <Menu.Item>Other Application...</Menu.Item>
          </Menu.SubContent>
        </Menu.Sub>
        <Menu.Sub>
          <Menu.SubTrigger>Share</Menu.SubTrigger>
          <Menu.SubContent>
            <Menu.Item>Copy Link</Menu.Item>
            <Menu.Item>Email</Menu.Item>
            <Menu.Sub>
              <Menu.SubTrigger>Social Media</Menu.SubTrigger>
              <Menu.SubContent>
                <Menu.Item>Twitter</Menu.Item>
                <Menu.Item>LinkedIn</Menu.Item>
                <Menu.Item>Facebook</Menu.Item>
              </Menu.SubContent>
            </Menu.Sub>
          </Menu.SubContent>
        </Menu.Sub>
        <Menu.Separator />
        <Menu.Item>Rename</Menu.Item>
        <Menu.Item disabled>Delete</Menu.Item>
      </Menu.Content>
    </Menu>
  );
}
 

Toolbar Dropdown

Dropdown menu of actions with keyboard shortcuts and a disabled item.

import { Menu, Button } from "ui-lab-components";
import { FaChevronDown } from "react-icons/fa6";
 
export const metadata = {
  title: "Toolbar Dropdown",
  description: "Dropdown menu of actions with keyboard shortcuts and a disabled item.",
};
 
export default function Example() {
  return (
    <Menu type="pop-over">
      <Menu.Trigger>
        <Button variant="ghost">
          File <FaChevronDown className="w-3 h-3 ml-1" />
        </Button>
      </Menu.Trigger>
      <Menu.Content align="start">
        <Menu.Item onSelect={() => {}}>
          New file
          <Menu.Shortcut>⌘N</Menu.Shortcut>
        </Menu.Item>
        <Menu.Item onSelect={() => {}}>
          Open…
          <Menu.Shortcut>⌘O</Menu.Shortcut>
        </Menu.Item>
        <Menu.Item onSelect={() => {}}>
          Save
          <Menu.Shortcut>⌘S</Menu.Shortcut>
        </Menu.Item>
        <Menu.Separator />
        <Menu.Item disabled>Recent files</Menu.Item>
      </Menu.Content>
    </Menu>
  );
}
 

Table Row Actions

Per-row overflow menu in a table, with a destructive action separated from neutral ones.

DocumentUpdated
Q3 roadmap2h ago
Pricing reviewyesterday
Hiring plan3 days ago
import { Menu, Button } from "ui-lab-components";
import { FaEllipsis } from "react-icons/fa6";
 
export const metadata = {
  title: "Table Row Actions",
  description: "Per-row overflow menu in a table, with a destructive action separated from neutral ones.",
};
 
const rows = [
  { id: "doc_1", name: "Q3 roadmap", updated: "2h ago" },
  { id: "doc_2", name: "Pricing review", updated: "yesterday" },
  { id: "doc_3", name: "Hiring plan", updated: "3 days ago" },
];
 
export default function Example() {
  return (
    <table className="w-full text-sm border-collapse">
      <thead>
        <tr className="border-b border-background-700">
          <th className="text-left py-2 px-3 font-medium text-foreground-200">Document</th>
          <th className="text-left py-2 px-3 font-medium text-foreground-200">Updated</th>
          <th className="py-2 px-3" />
        </tr>
      </thead>
      <tbody>
        {rows.map((row) => (
          <tr key={row.id} className="border-b border-background-700 last:border-0">
            <td className="py-2 px-3">{row.name}</td>
            <td className="py-2 px-3 text-foreground-400">{row.updated}</td>
            <td className="py-2 px-3 text-right">
              <Menu type="pop-over">
                <Menu.Trigger>
                  <Button
                    icon={<FaEllipsis />}
                    size="icon"
                    variant="ghost"
                    styles="p-2"
                    aria-label={`Actions for ${row.name}`}
                  />
                </Menu.Trigger>
                <Menu.Content align="end">
                  <Menu.Item onSelect={() => {}}>Open</Menu.Item>
                  <Menu.Item onSelect={() => {}}>Rename</Menu.Item>
                  <Menu.Item onSelect={() => {}}>Duplicate</Menu.Item>
                  <Menu.Separator />
                  <Menu.Item
                    onSelect={() => {}}
                    styles={{ root: "text-destructive" }}
                  >
                    Delete
                  </Menu.Item>
                </Menu.Content>
              </Menu>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
 

Context Menu

Right-click anywhere in the surface to open the menu at the cursor position.

import { Menu } from "ui-lab-components";
 
export const metadata = {
  title: "Context Menu",
  description: "Right-click anywhere in the surface to open the menu at the cursor position.",
};
 
export default function Example() {
  return (
    <Menu type="context-menu">
      <Menu.Trigger>
        <div className="flex items-center justify-center w-80 h-32 border border-dashed border-background-700 rounded-sm text-sm text-foreground-400 select-none">
          Right-click anywhere in this area
        </div>
      </Menu.Trigger>
      <Menu.Content>
        <Menu.Item onSelect={() => {}}>
          Cut
          <Menu.Shortcut>⌘X</Menu.Shortcut>
        </Menu.Item>
        <Menu.Item onSelect={() => {}}>
          Copy
          <Menu.Shortcut>⌘C</Menu.Shortcut>
        </Menu.Item>
        <Menu.Item onSelect={() => {}}>
          Paste
          <Menu.Shortcut>⌘V</Menu.Shortcut>
        </Menu.Item>
        <Menu.Separator />
        <Menu.Item onSelect={() => {}} styles={{ root: "text-destructive" }}>
          Delete
        </Menu.Item>
      </Menu.Content>
    </Menu>
  );
}
 

View Options

Mixed checkbox and radio items for toggling display state and selecting a single density.

"use client";
 
import { useState } from "react";
import { Menu, Button } from "ui-lab-components";
 
export const metadata = {
  title: "View Options",
  description: "Mixed checkbox and radio items for toggling display state and selecting a single density.",
};
 
export default function Example() {
  const [showGrid, setShowGrid] = useState(true);
  const [showRulers, setShowRulers] = useState(false);
  const [density, setDensity] = useState("comfortable");
 
  return (
    <Menu type="pop-over">
      <Menu.Trigger>
        <Button>View</Button>
      </Menu.Trigger>
      <Menu.Content align="start">
        <Menu.Label>Display</Menu.Label>
        <Menu.CheckboxItem checked={showGrid} onCheckedChange={setShowGrid}>
          Show grid
        </Menu.CheckboxItem>
        <Menu.CheckboxItem checked={showRulers} onCheckedChange={setShowRulers}>
          Show rulers
        </Menu.CheckboxItem>
        <Menu.Separator />
        <Menu.Label>Density</Menu.Label>
        <Menu.RadioGroup value={density} onValueChange={setDensity}>
          <Menu.RadioItem value="compact">Compact</Menu.RadioItem>
          <Menu.RadioItem value="comfortable">Comfortable</Menu.RadioItem>
          <Menu.RadioItem value="spacious">Spacious</Menu.RadioItem>
        </Menu.RadioGroup>
      </Menu.Content>
    </Menu>
  );
}
 
UI Lab