Skip to content

Dropdown

<pa-dropdown> | PaDropdown

A versatile dropdown select component with floating labels, validation support, and icon integration. Built on native HTML select elements for accessibility while providing enhanced styling and functionality.

vue
<template>
  <pa-dropdown 
    v-model="selectedValue"
    label="Choose an option" 
    :items="[
      { value: '', label: 'Select...' },
      { value: 'option1', label: 'Option 1' },
      { value: 'option2', label: 'Option 2' },
      { value: 'option3', label: 'Option 3' }
    ]" 
  />
</template>

<script setup>
import { ref } from 'vue'

const selectedValue = ref('')
</script>

Examples

Basic Usage

The simplest way to use a dropdown with predefined options.

vue
<template>
  <pa-dropdown 
    v-model="country"
    label="Select Country" 
    :items="[
      { value: '', label: 'Choose country...' },
      { value: 'us', label: 'United States' },
      { value: 'ca', label: 'Canada' },
      { value: 'uk', label: 'United Kingdom' },
      { value: 'au', label: 'Australia' }
    ]" 
    @update:modelValue="handleCountryChange"
  />
</template>

<script setup>
import { ref } from 'vue'

const country = ref('')

const handleCountryChange = (value) => {
  console.log('Selected country:', value)
}
</script>

Using Slots for Options

For more complex option content or when working with dynamic templates.

vue
<template>
  <pa-dropdown v-model="priority" label="Priority Level">
    <option value="" disabled>Select priority...</option>
    <option value="low">🟢 Low Priority</option>
    <option value="medium">🟡 Medium Priority</option>
    <option value="high">🔴 High Priority</option>
    <option value="urgent">🚨 Urgent</option>
  </pa-dropdown>
</template>

<script setup>
import { ref } from 'vue'

const priority = ref('')
</script>

With Icons

Add prepend or append icons to enhance the dropdown interface.

vue
<template>
  <div style="display: flex; flex-direction: column; gap: 1rem;">
    <pa-dropdown 
      v-model="accountType"
      label="Account Type" 
      prepend-icon="user-solid"
      :items="[
        { value: '', label: 'Select account type...' },
        { value: 'personal', label: 'Personal Account' },
        { value: 'business', label: 'Business Account' },
        { value: 'enterprise', label: 'Enterprise Account' }
      ]" 
    />
    <pa-dropdown 
      v-model="paymentMethod"
      label="Payment Method" 
      append-icon="credit-card-solid"
      :items="[
        { value: '', label: 'Choose payment method...' },
        { value: 'card', label: 'Credit Card' },
        { value: 'bank', label: 'Bank Transfer' },
        { value: 'paypal', label: 'PayPal' }
      ]" 
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const accountType = ref('')
const paymentMethod = ref('')
</script>

Required Field with Validation

Dropdown with required validation and error handling.

vue
<template>
    <pa-dropdown 
      v-model="requiredValue"
      label="Required Selection" 
      :required="true"
      :items="[
        { value: '', label: 'Please select...' },
        { value: 'option1', label: 'Option 1' },
        { value: 'option2', label: 'Option 2' },
        { value: 'option3', label: 'Option 3' }
      ]" 
    />
  </form>
</template>

Disabled State

Not connected

Dropdown in disabled state for read-only scenarios.

vue
<template>
  <pa-dropdown 
    v-model="status"
    label="Status (Read Only)" 
    :disabled="true"
    :items="[
      { value: 'active', label: 'Active' },
      { value: 'inactive', label: 'Inactive' },
      { value: 'pending', label: 'Pending' }
    ]" 
  />
</template>

Interactive Example

A complete form example showing dropdown integration with other components.

vue
<template>
  <form @submit.prevent="createListing" class="listing-form">
    <pa-dropdown 
      v-model="category"
      label="Category" 
      prepend-icon="tags-solid"
      :items="categoryOptions"
      :required="true"
    />
    <pa-dropdown 
      v-model="condition"
      label="Condition" 
      :items="conditionOptions"
      :required="true"
    />
    <pa-button type="submit" variant="primary">
      Create Listing
    </pa-button>
  </form>
</template>

Importing

typescript
import { PaDropdown } from '@payadvantage/ui-components'

Properties

NameDescriptionReflectsTypeDefault
modelValueThe selected value (used with v-model).nostring | null''
labelThe floating label text.nostring''
itemsArray of options when not using slots.noPaDropdownGroupItem[][]
requiredMakes the dropdown required for validation.nobooleanfalse
disabledDisables the dropdown.nobooleanfalse
readonlyMakes the dropdown read-only.nobooleanfalse
prependIconIcon to display on the left side.nostring''
appendIconIcon to display on the right side (overrides default dropdown arrow).nostring''
iconVariantIcon color variant.no'light' | 'dark''dark'
sfSelectorCustom selector for testing frameworks.nostring''

Learn more about component properties.

Events

NameDescriptionEvent Detail
update:modelValueEmitted when the selected value changes (for v-model).string - The new selected value
focusEmitted when the dropdown gains focus.Event - The focus event
blurEmitted when the dropdown loses focus.Event - The blur event
appendClickEmitted when the append icon is clicked.PaDropdown - The component instance
prependClickEmitted when the prepend icon is clicked.PaDropdown - The component instance

Learn more about component events.

Slots

NameDescription
defaultThe option elements. Use when you need custom option content or dynamic templates.
vue
<template>
  <pa-dropdown label="Custom Options">
    <option value="">Choose...</option>
    <option value="1">Option with 🎯 emoji</option>
    <option value="2">Option with custom formatting</option>
  </pa-dropdown>
</template>

Learn more about using slots.

Methods

NameDescriptionParameters
focus()Programmatically focus the dropdown.None
vue
<template>
  <pa-dropdown ref="dropdownRef" label="Focus me" />
  <pa-button @click="focusDropdown">Focus Dropdown</pa-button>
</template>

<script setup>
import { ref } from 'vue'

const dropdownRef = ref()

const focusDropdown = () => {
  dropdownRef.value?.focus()
}
</script>

Types

typescript
interface PaDropdownGroupItem {
  value: string
  label: string
}

Dependencies

  • PaIcon: Used for prepend, append, and dropdown arrow icons
  • Validation Mixin: Provides built-in validation capabilities with visual feedback
  • Bootstrap CSS: Uses Bootstrap's form control and custom select styling
  • Design Tokens: CSS custom properties for consistent theming

Design Notes

The dropdown component provides:

  • Native accessibility: Built on standard HTML select elements for screen reader compatibility
  • Floating labels: Smooth label animations based on focus and selection state
  • Flexible options: Support for both prop-based and slot-based option definitions
  • Icon integration: Optional prepend and append icons with click handling
  • Validation support: Built-in validation with visual error states
  • Responsive design: Adapts to container width and screen sizes

Visual Design

  • Uses floating label pattern for space efficiency
  • Custom dropdown arrow icon that rotates based on open/closed state
  • Validation states with clear visual feedback
  • Icon positioning that doesn't interfere with text content
  • Consistent styling with other form components

Interaction Patterns

  • Click to open native dropdown menu
  • Keyboard navigation through options
  • Automatic validation on blur events
  • Icon click events for custom actions
  • Focus management for accessibility

This component is ideal for:

  • Form field selection inputs
  • Filter and sorting controls
  • Configuration and settings interfaces
  • Multi-step form navigation
  • Data entry applications requiring validated selections

Accessibility Notes

  • Uses semantic HTML select elements for proper screen reader support
  • Maintains native keyboard navigation (arrow keys, Enter, Escape)
  • Required fields are properly announced to assistive technologies
  • Validation states are communicated both visually and programmatically
  • Focus management follows standard form control patterns
  • Label association is maintained for screen reader compatibility
  • Custom icons don't interfere with accessibility features