Skip to content

Overlays

Dropdown menu

A button that opens a short list of actions or options.

import { DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuLabel } from '@jsonresume/ui'Source(opens in a new tab)

Examples

ActionsIcons, a shortcut hint and a destructive item last.
Show code
dropdown-menu/actions.tsx
'use client';

import {
  Button,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@jsonresume/ui';
import { Copy, ExternalLink, FileText, Trash2 } from 'lucide-react';

export default function DropdownMenuActions() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button>Job actions</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuLabel>Senior Engineer · Stripe</DropdownMenuLabel>
        <DropdownMenuItem icon={<FileText />}>
          Write cover letter
        </DropdownMenuItem>
        <DropdownMenuItem icon={<ExternalLink />}>
          Open listing
        </DropdownMenuItem>
        <DropdownMenuItem icon={<Copy />} shortcut="⌘C">
          Copy link
        </DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem icon={<Trash2 />} tone="danger">
          Hide this job
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
OptionsCheckbox items keep the menu open while toggling.
Show code
dropdown-menu/checkboxes.tsx
'use client';

import {
  Button,
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuTrigger,
} from '@jsonresume/ui';
import { useState } from 'react';

const columns = ['Company', 'Location', 'Salary', 'Match'];

export default function DropdownMenuCheckboxes() {
  const [visible, setVisible] = useState(new Set(columns));
  const toggle = (c: string) =>
    setVisible((v) => {
      const next = new Set(v);
      if (next.has(c)) next.delete(c);
      else next.add(c);
      return next;
    });
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button>Columns ({visible.size})</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuLabel>Show columns</DropdownMenuLabel>
        {columns.map((c) => (
          <DropdownMenuCheckboxItem
            key={c}
            checked={visible.has(c)}
            onCheckedChange={() => toggle(c)}
            onSelect={(e) => e.preventDefault()}
          >
            {c}
          </DropdownMenuCheckboxItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

Usage

Do

  • Keep menus to about seven items.
  • Put destructive actions last, after a separator, in the danger tone.

Don’t

  • Hide the only way to do something important in a menu.
  • Nest menus.

Accessibility

  • Opens with Enter, Space or Arrow Down; arrows move, Enter selects, Escape closes and returns focus.
  • Type-ahead jumps to items by their first letter.

Props

<DropdownMenuContent>

No props of its own; accepts the attributes of the element it renders.

<DropdownMenuItem>

Also accepts the attributes of the element DropdownMenuItem renders.
PropTypeDefaultDescription
iconReactNode–
shortcutstring–
tonedefaultdanger–Destructive actions (delete, sign out of all devices) read in red.

<DropdownMenuCheckboxItem>

No props of its own; accepts the attributes of the element it renders.

<DropdownMenuLabel>

No props of its own; accepts the attributes of the element it renders.