Logo

Dropdown Menu

Menus with hover and click triggers, submenus, and keyboard support.

Preview

Usage

TS

import { FrDropdownMenuModule } from '@frame-ui-ng/components/dropdown-menu';

HTML

<div frDropdownMenu>
  <button type="button" [frDropdownMenuTrigger]="menu">Open actions</button>

  <ng-template #menu="frDropdownMenuContent" frDropdownMenuContent>
    <div frDropdownMenuPanel>
      <button frDropdownMenuItem type="button">
        <ng-icon name="tablerUser" size="14" />
        <span>Open profile</span>
      </button>

      <button frDropdownMenuCheckboxItem [checked]="true" type="button">
        <span frDropdownMenuItemIndicator>
          <ng-icon name="tablerCheck" size="14" />
        </span>
        <span>Pin in sidebar</span>
      </button>
    </div>
  </ng-template>
</div>

Examples

Basic actions

Use the default item primitive for simple action lists, grouping related commands with labels and separators when the menu needs more structure.

Submenus

Submenus work well for secondary branches like sharing, exporting, or invite flows that should stay close to the current action list.

Shortcuts and destructive actions

Use shortcut copy for power-user hints and the destructive variant for actions that need a stronger warning without leaving the menu pattern.

Hover trigger mode

Switch to `hover` or `both` when a menu should behave more like a classic application menubar or nested navigation flyout.

Custom Styling

Scope token overrides to a wrapper when a product area needs a softer menu radius, a different shadow, or custom hover treatment without changing the dropdown structure or behavior.

Token Inspector

The trigger itself is app-owned, so the inspector focuses on the menu surface: panel, labels, rows, shortcuts, and state indicators. Hover a region to inspect the token contract and click to pin the popover.

Quick actions

Design Tokens

Dropdown menu tokens style the overlay surface and its internal rows. The trigger itself remains host-app owned, so pair these menu tokens with whatever button or trigger primitive your app already uses.

SCSS


  --frame-dropdown-menu-panel-min-width: 13rem;
  --frame-dropdown-menu-panel-radius: var(--frame-radius-md);
  --frame-dropdown-menu-panel-bg: var(--frame-surface);
  --frame-dropdown-menu-panel-color: var(--frame-surface-foreground);
  --frame-dropdown-menu-panel-border: var(--frame-border);
  --frame-dropdown-menu-panel-shadow: var(--frame-shadow-md);
  --frame-dropdown-menu-panel-padding: 0.25rem;
  --frame-dropdown-menu-label-color: var(--frame-muted-foreground);
  --frame-dropdown-menu-label-font-size: 0.75rem;
  --frame-dropdown-menu-label-font-weight: 600;
  --frame-dropdown-menu-separator-margin: 0.25rem -0.25rem;
  --frame-dropdown-menu-separator-bg: var(--frame-border);
  --frame-dropdown-menu-item-gap: 0.5rem;
  --frame-dropdown-menu-item-height: 2rem;
  --frame-dropdown-menu-item-radius: calc(var(--frame-radius-md) - 0.125rem);
  --frame-dropdown-menu-item-padding: 0.375rem 0.5rem;
  --frame-dropdown-menu-item-font-size: 0.875rem;
  --frame-dropdown-menu-item-hover-bg: var(--frame-accent);
  --frame-dropdown-menu-item-hover-color: var(--frame-accent-foreground);
  --frame-dropdown-menu-item-disabled-opacity: 0.5;
  --frame-dropdown-menu-item-destructive-color: var(--frame-destructive);
  --frame-dropdown-menu-item-destructive-hover-bg: color-mix(in srgb, var(--frame-destructive) 12%, var(--frame-surface));
  --frame-dropdown-menu-item-destructive-hover-color: var(--frame-destructive);
  --frame-dropdown-menu-item-inset-padding: 2rem;
  --frame-dropdown-menu-shortcut-gap: 0.75rem;
  --frame-dropdown-menu-shortcut-color: var(--frame-muted-foreground);
  --frame-dropdown-menu-shortcut-font-size: 0.75rem;
  --frame-dropdown-menu-indicator-size: 1rem;
  --frame-dropdown-menu-motion-duration: 140ms;
  --frame-dropdown-menu-motion-easing: cubic-bezier(0.16, 1, 0.3, 1);
  --frame-dropdown-menu-motion-distance: 0.2rem;
  --frame-dropdown-menu-motion-scale: 0.98;