Components

Dropdown

Let users pick one option from a rich, searchable list.

Import

import { Dropdown } from "@dr-max/ui/dropdown"

The entry carries its own precompiled CSS (including the styles of the Icon, Required and Spinner parts it composes) — no extra style imports needed.

Usage

Unlike the native Select, the dropdown renders a custom listbox panel. Pass the choices via the options prop ({ label, labelSecondary?, value, disabled?, searchableText? }) and bind the selected value with v-model:

<script setup lang="ts">
import { Dropdown } from "@dr-max/ui/dropdown"
import { ref } from "vue"

const country = ref("")

const options = [
  { label: "Czechia", value: "cz" },
  { label: "Slovakia", value: "sk" },
  { label: "Poland", value: "pl" }
]
</script>

<template>
  <Dropdown v-model="country" label="Country" placeholder="Choose a country" :options="options" />
</template>

For documentation and visual tests the panel can be rendered expanded on first render with default-open.

Secondary labels

labelSecondary renders right-aligned inside the option — useful for prices or codes:

<script setup lang="ts">
const options = [
  { label: "Pickup point", labelSecondary: "Free", value: "pickup" },
  { label: "Courier", labelSecondary: "79 Kč", value: "courier" },
  { label: "Same-day courier", labelSecondary: "149 Kč", value: "same-day" }
]
</script>

search-enabled renders a search field inside the panel. filter-mode decides how the term matches option labels (startsWith or includes) — matching is diacritics-insensitive, and searchableText on an option is matched instead of its label when present:

<template>
  <Dropdown
    v-model="country"
    label="Country"
    placeholder="Choose a country"
    :options="options"
    search-enabled
    filter-mode="includes"
    search-placeholder="Search countries"
    no-results-label="No country found"
  />
</template>

Loading

loading shows a loading row inside the panel instead of the options, with loading-label rendered next to the spinner:

<template>
  <Dropdown
    v-model="pickupPoint"
    label="Pickup point"
    placeholder="Choose a pickup point"
    loading
    loading-label="Loading pickup points…"
  />
</template>

Validation errors

errors renders validation messages below the trigger once touched marks the validation as active:

<template>
  <Dropdown
    v-model="country"
    label="Country"
    placeholder="Choose a country"
    :options="options"
    touched
    :errors="[{ label: 'Choose your country', param: 'required' }]"
  />
</template>

Disabled

<template>
  <Dropdown v-model="country" label="Country" placeholder="Choose a country" :options="options" disabled />
</template>

Playground

<script setup lang="ts">
import { Dropdown } from '@dr-max/ui/dropdown'

const options = [
  { label: 'Czechia', value: 'cz' },
  { label: 'Slovakia', value: 'sk' },
  { label: 'Poland', value: 'pl' },
  { label: 'Romania', value: 'ro' },
  { label: 'Italy', value: 'it' }
]
</script>

<template>
  <Dropdown label="Country" placeholder="Choose a country" :options="options" />
</template>
Dr. Max Design System • © 2026