Skip to content

ExDropdown

html
<ExDropdown
    v-model="dropdownModel"
    v-slot="{ labelAttrs, isOpen }"
>
    <label v-bind="labelAttrs" class="mb-2">Dropdown Label:</label>
    <ExDropdownTrigger>Dropdown Button</ExDropdownTrigger>

    <ExDropdownList>
        <template v-for="(item) in items" :key="item.id">
            <ExDropdownListItem v-slot="{ active }">
                <div>item.text</div>
            </ExDropdownListItem>
        </template>
    </ExDropdownList>
</ExDropdown>

Interact

Props: ExDropdown

as

TypeDefaultRequired
string componenttemplatefalse

Description: Sets the element type of ex-dialog-close. Any custom vue component can also be passed.


modelValue

TypeDefaultRequired
booleanfalsetrue

Description: Controls the display of dropdown list.


left

TypeDefaultRequired
booleanfalsefalse

Description: Positions dropdown content to the left of the trigger


TypeDefaultRequired
booleanfalsefalse

Description: Positions dropdown content to the right of the trigger


closeOnClick

TypeDefaultRequired
booleantruefalse

Description: Choose whether dropdown should be closed on content click


Emits

NameDescription

update:modelValue

This v-model update gets emitted when any value is selected from the list

html
<ExDropdown v-model="dropdownVisibility" ...>
    ...
</ExDropdown>

Slots

NameDescription

default

The default Vue slot.

js
{
    open: Function, // opens dropdown
    close: Function, // closes dropdown
    isOpen: boolean,
    labelAttrs: {
        id: string, // element ID will be set automatically
        for: string // refers to dropdown-trigger-id
    }
}

Props: ExDropdownTrigger

as

TypeDefaultRequired
string componenttemplatefalse

Description: Sets the element type of ex-dropdown-trigger. Any custom vue component can also be passed.


disabled

TypeDefaultRequired
booleanfalsefalse

Description: Enables / Disables dropdown trigger.


Slots

NameDescription
defaultThe default Vue slot

Props: ExDropdownList

as

TypeDefaultRequired
string componenttemplatefalse

Description: Sets the element type of ex-dropdown-list. Any custom vue component can also be passed.


minWidth

TypeDefaultRequired
string numberWidth of the dropdown triggerfalse

Description: Sets the min-width of ex-dropdown-list. Values can also be percentages.


maxWidth

TypeDefaultRequired
string numberundefinedfalse

Description: Sets the max-width of ex-dropdown-list. Values can also be percentages.


maxHeight

TypeDefaultRequired
string numberundefinedfalse

Description: Sets the max-height of ex-dropdown-list. Values can also be percentages.


Slots

NameDescription

default

The default Vue slot.

js
{
    isOpen: boolean
}

Props: ExDropdownListItem

as

TypeDefaultRequired
string componentdivfalse

Description: Sets the element type of ex-dropdown-list-item. Any custom vue component can also be passed.


disabled

TypeDefaultRequired
booleanfalsefalse

Description: Enables / Disables dropdown list item.


Slots

NameDescription

default

The default Vue slot.

js
{
    active: boolean
    disabled: boolean
}

Examples

Sample Dropdown

html
<ExDropdown
    v-model="movieModel"
    v-slot="{ labelAttrs, isOpen }"
>
    <div class="flex flex-col">
        <label v-bind="labelAttrs" class="mb-2">Position:</label>
        <ExDropdownTrigger class="gap-x-3 focus:ring focus:ring-gray-500 focus:transition-all bg-body/10 sm:w-48 flex items-center justify-between w-full px-4 py-1 rounded-lg outline-none">
            <span class="text-base">{{ currentMovie.text }}</span>
            <span :class="[isOpen ? 'rotate-0': 'rotate-180']" class="pt-1 transition-transform transform">
                &#8963;
            </span>
        </ExDropdownTrigger>
    </div>
    <ExDropdownList class="bg-white/10 backdrop-blur-2xl border-border p-2 mt-1 overflow-y-auto border rounded-lg shadow-xl outline-none">
        <template v-for="(movie) in movies" :key="movie.value">
            <ExDropdownListItem v-slot="{ active }" as="template">
                <div
                    @click="updateMovie(movie.value)"
                    :class="[{ 'bg-body/10': active }]"
                    class="text-body px-2 py-1 rounded-md outline-none cursor-pointer"
                >
                    {{ movie.text }}
                </div>
            </ExDropdownListItem>
        </template>
    </ExDropdownList>
</ExDropdown>
js
import { nextTick, ref, watch } from 'vue'

import ExDropdown from 'ExDropdown/ExDropdown.vue' // import is for demo purpose, make sure the correct package reference is used
import ExDropdownTrigger from 'ExDropdown/ExDropdownTrigger.vue'
import ExDropdownList from 'ExDropdown/ExDropdownList.vue'
import ExDropdownListItem from 'ExDropdown/ExDropdownListItem.vue'

interface Movie {
    text: string,
    value: string
}

const placeholder: Movie = {
    text: 'Select Movie',
    value: 'none'
}

const movies: Movie[] = [
    { text: 'Blade Runner 2049', value: 'blade-runner-2049' },
    { text: 'Monarch', value: 'monarch' }
]

const movieModel = ref(false)
const currentMovie = ref<Movie>(placeholder)
const updateMovie = (value: string) => {
    currentMovie.value = movies.find(i => i.value === value) ?? placeholder
}

Released under the MIT License.