Forms

SelectMenu

A searchable dropdown select with icons, avatars, grouped items, descriptions, and custom rendering. Built on bits-ui Combobox with full keyboard navigation.

Playground

Experiment with different props in real-time.

Basic Usage

Pass items and use bind:value. Items are searchable by default.

<script lang="ts">
  import { SelectMenu } from 'sv5ui';

  let value = $state('');

  const items = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'orange', label: 'Orange' },
    { value: 'grape', label: 'Grape' },
    { value: 'mango', label: 'Mango' }
  ];
</script>

<SelectMenu {items} bind:value placeholder="Select a fruit..." />

With Icons

Add Iconify icons to items.

<SelectMenu
  placeholder="Select status..."
  items={[
    { value: 'active', label: 'Active', icon: 'lucide:check-circle' },
    { value: 'paused', label: 'Paused', icon: 'lucide:pause-circle' },
    { value: 'closed', label: 'Closed', icon: 'lucide:x-circle' }
  ]}
/>

With Avatar

Display avatars alongside items.

<SelectMenu
  placeholder="Assign to..."
  items={[
    { value: 'john', label: 'John Doe', avatar: { src: 'https://i.pravatar.cc/40?u=1', alt: 'John' } },
    { value: 'jane', label: 'Jane Smith', avatar: { src: 'https://i.pravatar.cc/40?u=2', alt: 'Jane' } },
    { value: 'bob', label: 'Bob Wilson', avatar: { src: 'https://i.pravatar.cc/40?u=3', alt: 'Bob' } }
  ]}
/>

With Description

Add secondary text to items.

<SelectMenu
  placeholder="Select a plan..."
  items={[
    { value: 'free', label: 'Free', description: '5GB storage, basic features' },
    { value: 'pro', label: 'Pro', description: '50GB storage, advanced analytics' },
    { value: 'enterprise', label: 'Enterprise', description: 'Unlimited storage, priority support' }
  ]}
/>

Grouped Items

Use type: 'label' for headings and type: 'separator' for dividers.

<SelectMenu
  placeholder="Select a framework..."
  items={[
    { type: 'label', label: 'Frontend' },
    { value: 'svelte', label: 'Svelte', icon: 'logos:svelte-icon' },
    { value: 'react', label: 'React', icon: 'logos:react' },
    { value: 'vue', label: 'Vue', icon: 'logos:vue' },
    { type: 'separator' },
    { type: 'label', label: 'Backend' },
    { value: 'node', label: 'Node.js', icon: 'logos:nodejs-icon' },
    { value: 'python', label: 'Python', icon: 'logos:python' },
    { value: 'go', label: 'Go', icon: 'logos:go' }
  ]}
/>

Variants

4 visual styles for the trigger.

<SelectMenu variant="outline" placeholder="Outline" {items} />
<SelectMenu variant="soft" placeholder="Soft" {items} />
<SelectMenu variant="subtle" placeholder="Subtle" {items} />
<SelectMenu variant="ghost" placeholder="Ghost" {items} />

Sizes

5 sizes.

<SelectMenu size="xs" placeholder="Extra Small" {items} />
<SelectMenu size="sm" placeholder="Small" {items} />
<SelectMenu size="md" placeholder="Medium" {items} />
<SelectMenu size="lg" placeholder="Large" {items} />
<SelectMenu size="xl" placeholder="Extra Large" {items} />

Colors

Visible with highlight active.

<SelectMenu color="primary" highlight placeholder="Primary" {items} />
<SelectMenu color="success" highlight placeholder="Success" {items} />
<SelectMenu color="warning" highlight placeholder="Warning" {items} />
<SelectMenu color="error" highlight placeholder="Error" {items} />

Search & Filtering

Items are searchable by default. Customize with filterFields or disable with ignoreFilter.

<!-- Default search (searches label and value) -->
<SelectMenu placeholder="Search items..." {items} />

<!-- Custom search fields -->
<SelectMenu
  placeholder="Search by description..."
  filterFields={['label', 'description']}
  items={[
    { value: 'free', label: 'Free', description: '5GB storage' },
    { value: 'pro', label: 'Pro', description: '50GB storage' },
    { value: 'enterprise', label: 'Enterprise', description: 'Unlimited' }
  ]}
/>

<!-- Disable filtering (server-side) -->
<SelectMenu placeholder="Server-side..." ignoreFilter {items} />

Loading

Show a spinner.

<SelectMenu loading placeholder="Loading..." {items} />

Disabled

Disable the entire menu or individual items.

<SelectMenu disabled placeholder="Disabled" {items} />

<!-- Individual disabled items -->
<SelectMenu
  placeholder="Some items disabled"
  items={[
    { value: 'active', label: 'Active' },
    { value: 'disabled', label: 'Disabled option', disabled: true },
    { value: 'another', label: 'Another active' }
  ]}
/>

Controlled

Use bind:value for two-way binding.

Selected: none

<script lang="ts">
  import { SelectMenu, Button } from 'sv5ui';

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

<SelectMenu {items} bind:value placeholder="Pick one..." />
<p>Selected: {value || 'none'}</p>
<Button size="sm" variant="outline" label="Reset" onclick={() => value = ''} />

UI Slots

Use the ui prop to override classes on internal elements.

SlotDescription
rootRoot wrapper element
baseTrigger button element
leadingLeading section container
leadingIconLeading icon element
leadingAvatarLeading avatar element
trailingTrailing section container
trailingIconTrailing icon (chevron)
valueSelected value text
placeholderPlaceholder text
contentDropdown content container
inputSearch input element
viewportScrollable items viewport
emptyEmpty state container
groupLabelGroup label/heading
separatorVisual separator between groups
itemIndividual item container
itemIconIcon in item
itemAvatarAvatar in item
itemLabelItem label text
itemDescriptionItem description text
itemIndicatorSelected indicator (checkmark)

Snippets

Custom rendering for trigger and dropdown content.

SnippetDescription
leadingSlotCustom content before selected value on trigger
trailingSlotCustom content after selected value on trigger
itemComplete item rendering (receives item, index, selected)
itemLeadingItem leading section (receives item, index, selected)
itemLabelItem label section (receives item, index, selected)
itemTrailingItem trailing/indicator section (receives item, index, selected)
emptyEmpty state (receives searchTerm)
contentComplete dropdown content (receives open, searchTerm)

Props

PropTypeDefault
itemsSelectMenuItemType[][]
valuestring-
openbooleanfalse
placeholderstring-
searchPlaceholderstring'Search...'
variant'outline' | 'soft' | 'subtle' | 'ghost' | 'none''outline'
colorColorType'primary'
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'
highlightbooleanfalse
loadingbooleanfalse
disabledbooleanfalse
iconstring-
leadingIconstring-
trailingIconstring'lucide:chevron-down'
selectedIconstring'lucide:check'
avatarAvatarProps-
filterFieldsstring[]['label', 'value']
ignoreFilterbooleanfalse
emptyTextstring'No results found.'
requiredbooleanfalse
namestring-
refHTMLElement | nullnull
classstring-
uiRecord<Slot, Class>-

Item Props

Each selectable item accepts these properties. Use type: 'label' for headings and type: 'separator' for dividers.

PropTypeDefault
valuestring-
labelstring-
descriptionstring-
iconstring-
avatarAvatarProps-
disabledbooleanfalse