Menu

SvMenu: a dropdown / actions menu with submenus, separators, icons and keyboard shortcuts. Portalled + animated, full keyboard (arrows, Enter, Escape, ArrowRight/Left).

A live, editable Svelte 5 component example from the SvGrid gallery (Layout). Read the SvGrid UI component docs for the full API.

About this example

SvMenu in Svelte 5, a dropdown and actions menu with submenus, separators, icons and keyboard shortcut hints, driven by an items array. The panel portals to the body and animates in, and the keyboard covers arrows, Enter, Escape and ArrowRight and ArrowLeft to open and close submenus.

SvMenu - a dropdown / actions menu with submenus, separators, icons and keyboard shortcuts. Portalled + animated; full keyboard (arrows, Enter, Escape, ArrowRight/Left for submenus).

Imports, features and API used

Imports: @svgrid/grid

Frequently asked questions

How do I define a submenu?

Give an item a children array. It shows a chevron, opens on hover or ArrowRight and closes on ArrowLeft, nesting as deep as the items go.

How are separators and shortcuts shown?

An item with separator: true draws a divider, and an item's shortcut string renders right-aligned as a hint; the shortcut itself is bound by your app.

How is the menu opened?

Any trigger element passed as the menu's child toggles it on click; the panel positions next to the trigger and flips when there is no room.

Related documentation

Related articles

Source code (326-menu.svelte)

<script lang="ts">
  /**
   * SvMenu - a dropdown / actions menu with submenus, separators, icons and
   * keyboard shortcuts. Portalled + animated; full keyboard (arrows, Enter,
   * Escape, ArrowRight/Left for submenus).
   */
  import { SvMenu, SvButton } from '@svgrid/grid'
  import type { MenuItem } from '@svgrid/grid'

  let last = $state('')

  const items: MenuItem[] = [
    { label: 'New file', shortcut: 'Ctrl+N', onSelect: () => (last = 'New file') },
    { label: 'Open...', shortcut: 'Ctrl+O', onSelect: () => (last = 'Open') },
    { separator: true },
    {
      label: 'Share',
      children: [
        { label: 'Copy link', onSelect: () => (last = 'Copy link') },
        { label: 'Email', onSelect: () => (last = 'Email') },
        { separator: true },
        { label: 'Export as PDF', onSelect: () => (last = 'Export PDF') },
      ],
    },
    { label: 'Rename', shortcut: 'F2', onSelect: () => (last = 'Rename') },
    { separator: true },
    { label: 'Delete', shortcut: 'Del', onSelect: () => (last = 'Delete') },
    { label: 'Archived (disabled)', disabled: true },
  ]
</script>

<div class="wrap">
  <header>
    <h2>Menu</h2>
    <p>A dropdown menu with submenus, separators, shortcuts and full keyboard. Arrow to navigate, Enter to pick, ArrowRight opens a submenu.</p>
  </header>

  <div class="row">
    <SvMenu {items}>
      {#snippet anchor()}<SvButton variant="primary">File actions ▾</SvButton>{/snippet}
    </SvMenu>

    <SvMenu {items} ariaLabel="Row actions">
      {#snippet anchor()}<SvButton variant="outline">⋯</SvButton>{/snippet}
    </SvMenu>

    <span class="last">{last ? `Chose: ${last}` : 'Nothing chosen yet'}</span>
  </div>
</div>

<style>
  .wrap { padding: 20px; max-width: 620px; display: flex; flex-direction: column; gap: 18px; }
  header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
  header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; }
  .row { display: flex; align-items: center; gap: 14px; }
  .last { font-size: 13px; color: var(--sg-muted, #64748b); }
</style>

View this example on GitHub

More Layout examples

  • Account & security settings console - A real SaaS settings surface composed from the UI kit: SvMenubar app bar, promise + Undo-action toasts on save, SvPopconfirm on destructive rows, SvHoverCard teammate previews, and frame input adornments (leading icons, prefix affixes, masked API key). Profile / Team / Security tabs over SvCard + SvStat.
  • Invoice builder - An adornment-heavy money form: currency prefixes, % suffixes, masked tax IDs (frame adornments), line items with SvPopconfirm delete + Undo action toasts, live SvStat totals, an SvHoverCard tax hint, and a promise toast on Send. Pure UI-kit composition.
  • Operations KPI dashboard - A KPI console: SvStat + SvSparkline tiles, an SvGauge SLA dial, SvHoverCard drill-down previews per service, an SvMenubar toolbar (View / Range / Actions) and a promise toast on Refresh. Pure UI-kit composition, no grid dependency.
  • Form: rich field types - SvForm reaching the whole input suite from one schema - phone, country, mask, combobox, radio, slider, tags, datetime and file - plus per-field help text, a readonly field, column span, and a promise toast on submit.
  • Form: cascading fields - SvForm dependent selects - a child list derives from the parent value via a function `options`, and `dependsOn` clears the child when the parent changes so a stale selection never lingers. Country -> State -> City.