Skip to content
CodeAtlas UI

Navigation

Dropdown Menu

A floating action menu with items, labels and separators.

<script>
  import {
    DropdownMenu,
    DropdownMenuItem,
    DropdownMenuLabel,
    DropdownMenuSeparator,
    Button,
  } from "@codeatlasdev/ui";
</script>

<DropdownMenu>
  {#snippet triggerChild(props)}<Button {...props}>Open menu</Button>{/snippet}
  <DropdownMenuLabel>File actions</DropdownMenuLabel>
  <DropdownMenuItem onclick={edit}>{#snippet children()}Edit{/snippet}</DropdownMenuItem>
  <DropdownMenuSeparator />
  <DropdownMenuItem variant="destructive" onclick={remove}>{#snippet children()}Delete{/snippet}</DropdownMenuItem>
</DropdownMenu>

Keyboard support follows the WAI-ARIA menu pattern: Enter, Space or ArrowDown opens the menu on the first item, ArrowUp opens it on the last, arrows then move, Enter or Space selects, Escape closes and focus returns to the trigger. Tab closes the menu. Selecting an item closes it. The menu is a popover layer in the browser top layer, positioned with CSS anchor positioning where supported, so it stays on top of a dialog it is opened from. Pass an interactive trigger (Button, IconButton) through triggerChild and spread the received props on it. Use trigger only for non-interactive content such as text or an icon. Use DropdownMenuLabel for a non-interactive group heading and DropdownMenuSeparator for a divider.

Default

A button trigger with a label, items, a separator and a destructive item.

Code
svelte
<script lang="ts">
  import { DropdownMenu, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel, Button } from '@codeatlasdev/ui';
  import { Edit2, Copy, Trash2, Download } from '@lucide/svelte';

  let last = $state('');
</script>

<DropdownMenu>
  {#snippet triggerChild(props)}
    <Button variant="glass" {...props}>Open menu</Button>
  {/snippet}
  <DropdownMenuLabel>File actions</DropdownMenuLabel>
  <DropdownMenuItem onclick={() => (last = 'Edit')}>
    {#snippet children()}<Edit2 size={14} /> Edit{/snippet}
  </DropdownMenuItem>
  <DropdownMenuItem onclick={() => (last = 'Duplicate')}>
    {#snippet children()}<Copy size={14} /> Duplicate{/snippet}
  </DropdownMenuItem>
  <DropdownMenuItem onclick={() => (last = 'Download')}>
    {#snippet children()}<Download size={14} /> Download{/snippet}
  </DropdownMenuItem>
  <DropdownMenuSeparator />
  <DropdownMenuItem variant="destructive" onclick={() => (last = 'Delete')}>
    {#snippet children()}<Trash2 size={14} /> Delete{/snippet}
  </DropdownMenuItem>
</DropdownMenu>

{#if last}<span class="note" aria-live="polite">Last action: {last}</span>{/if}

<style>
  .note { font-size: var(--ca-font-size-body2); color: var(--ca-text-secondary); }
</style>

Icon trigger

An IconButton trigger. IconButton needs an aria-label.

Code
svelte
<script lang="ts">
  import { DropdownMenu, DropdownMenuItem, DropdownMenuLabel, IconButton } from '@codeatlasdev/ui';
  import { MoreHorizontal, Copy, Share2 } from '@lucide/svelte';
</script>

<DropdownMenu align="end">
  {#snippet triggerChild(props)}
    <IconButton aria-label="More options" {...props}><MoreHorizontal size={18} /></IconButton>
  {/snippet}
  <DropdownMenuLabel>Actions</DropdownMenuLabel>
  <DropdownMenuItem>
    {#snippet children()}<Share2 size={14} /> Share{/snippet}
  </DropdownMenuItem>
  <DropdownMenuItem>
    {#snippet children()}<Copy size={14} /> Copy link{/snippet}
  </DropdownMenuItem>
</DropdownMenu>
PropTypeDefaultDescription
triggerChildSnippet<[Record<string, unknown>]>–Interactive trigger. Receives the trigger props to spread onto your Button or IconButton.
triggerSnippet–Non-interactive trigger content (text, icon), wrapped in the menu's own button.
childrenSnippet–Menu content: items, labels and separators.
side'top' | 'right' | 'bottom' | 'left''bottom'Preferred side of the trigger.
align'start' | 'center' | 'end''start'Alignment against the trigger.
sideOffsetnumber6Distance from the trigger in pixels.
classstring''Extra CSS classes on the content.
PropTypeDefaultDescription
onclick() => void–Called when the item is selected.
variant'default' | 'destructive''default'destructive colors the item with the error token.
disabledbooleanfalsePrevents selection.
childrenSnippet–Item content, usually an icon and a label.
classstring''Extra CSS classes.
PropTypeDefaultDescription
childrenSnippet–Heading text.
classstring''Extra CSS classes.

DropdownMenuSeparator takes no props.