Skip to content
CodeAtlas UI

Navigation

Dropdown Menu

A floating action menu built on Bits UI with items, labels and separators.

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

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

Keyboard support comes from Bits UI: Enter or Space opens the menu, arrows move, Escape closes and focus returns to the trigger. 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.

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.