Drop-down list

SvDropDownList: a status / priority toolbar with grouped options, type-ahead and animated portalled panels driving a live issue list.

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

What this example shows

SvDropDownList - a production toolbar: compact single-select dropdowns for status and priority (grouped, type-ahead, portalled + animated). Copy-paste ready.

Imports, features and API used

Imports: @svgrid/grid

Source code (314-dropdownlist.svelte)

<script lang="ts">
  /**
   * SvDropDownList - a production toolbar: compact single-select dropdowns for
   * status and priority (grouped, type-ahead, portalled + animated). Copy-paste
   * ready.
   */
  import { SvDropDownList } from '@svgrid/grid'
  import type { ListOption } from '@svgrid/grid'

  const statuses: ListOption[] = [
    { value: 'todo', label: 'To do', group: 'Open' },
    { value: 'doing', label: 'In progress', group: 'Open' },
    { value: 'review', label: 'In review', group: 'Open' },
    { value: 'done', label: 'Done', group: 'Closed' },
    { value: 'wontfix', label: "Won't fix", group: 'Closed' },
  ]
  const priorities: ListOption[] = [
    { value: 'low', label: 'Low' },
    { value: 'med', label: 'Medium' },
    { value: 'high', label: 'High' },
    { value: 'urgent', label: 'Urgent' },
  ]
  let status = $state<string | number | null>('doing')
  let priority = $state<string | number | null>('high')
  const rows = 4
</script>

<div class="wrap">
  <header>
    <h2>Drop-down list</h2>
    <p>A compact single-select (no typing in the field) with grouped options, type-ahead and keyboard - toolbars, filters, cell editors.</p>
  </header>

  <div class="toolbar">
    <label class="f">Status<SvDropDownList options={statuses} value={status} onChange={(v) => (status = v)}>
      {#snippet item(o)}<span class="opt-row"><span class="opt-dot"></span>{o.label}</span>{/snippet}
      {#snippet footer()}<span class="opt-foot">{statuses.length} statuses</span>{/snippet}
    </SvDropDownList></label>
    <label class="f">Priority<SvDropDownList options={priorities} value={priority} onChange={(v) => (priority = v)} /></label>
  </div>

  <div class="issues">
    {#each Array(rows) as _, i (i)}
      <div class="issue">
        <span class="badge badge--{status}">{statuses.find((s) => s.value === status)?.label}</span>
        <span class="title">Issue #{1042 + i} - improve dashboard load time</span>
        <span class="pri pri--{priority}">{priorities.find((p) => p.value === priority)?.label}</span>
      </div>
    {/each}
  </div>
</div>

<style>
  .wrap { padding: 20px; max-width: 640px; display: flex; flex-direction: column; gap: 16px; }
  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; }
  .toolbar { display: flex; gap: 16px; flex-wrap: wrap; }
  .f { display: flex; flex-direction: column; gap: 5px; font-size: 12px; font-weight: 600; color: var(--sg-muted, #64748b); }
  .opt-row { display: flex; align-items: center; gap: 8px; }
  .opt-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--sg-accent, #4f46e5); flex: none; }
  .opt-foot { color: var(--sg-muted, #64748b); }
  .issues { display: flex; flex-direction: column; gap: 6px; }
  .issue { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--sg-border, #e2e8f0); border-radius: 8px; font-size: 13px; }
  .title { flex: 1; }
  .badge, .pri { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
  .badge { background: color-mix(in srgb, var(--sg-accent, #2563eb) 14%, transparent); color: var(--sg-accent, #2563eb); }
  .pri { color: var(--sg-muted, #64748b); border: 1px solid var(--sg-border, #e2e8f0); }
  .pri--urgent { color: #dc2626; border-color: #dc2626; }
  .pri--high { color: #ea580c; border-color: #ea580c; }
</style>

View this example on GitHub

Related documentation

Related articles

More Selection examples

  • Selection controls - List and overlay pickers: SvListBox (inline multi-select), SvDropDownList, SvComboBox (type to filter), SvAutoComplete (free text + suggestions), SvTagsInput (chips) and SvCountryInput (searchable, flags). Every popover portals out of the scroll container. Grid cell editors, standalone too.
  • List box - SvListBox: an assignee picker - inline multi-select with grouped options (departments), roving keyboard + type-ahead and a live summary.
  • Combo box - SvComboBox: a form field - type to filter a grouped, portalled list; the value must come from the list. With label + required validation.
  • Autocomplete - SvAutoComplete: a free-text search field with live suggestion shortcuts (any value accepted) - city search and a filter-syntax helper.
  • Resizable dropdowns - Built-in browser bounds detection - every picker panel (SvDropDownList / SvComboBox / SvAutoComplete) opens downward when there is room and flips upward automatically near the window edge. Plus a `resizable` prop that adds a bottom drag grip to the open panel (drag to grow/shrink; height sticks for the session; grip hides on an upward flip). A switch compares fixed-height vs resizable. Theme-aware (light/dark).