Skip to content

Dropdown

Dropdown component

GitHub Repo stars GitHub forks

Repository status

CircleCI codecov npm version license JavaScript Style Guide

Detailed changes for each release are documented in Changelog

If you are using vue 2.x version, please use v-dropdown 2.x version instead

Installation

Install v-dropdown component in to your project

sh
npm i v-dropdown
npm i v-dropdown
sh
yarn add v-dropdown
yarn add v-dropdown
sh
pnpm add v-dropdown
pnpm add v-dropdown

Usage

vue
<template>
  <Dropdown @visible-change="change">
    <!-- trigger element -->
    <template #trigger>
      <button type="button">Click me</button>
    </template>

    <!-- contents display in dropdown -->
    <div>
      some contents
    </div>
  </Dropdown>
</template>

<script setup>
import Dropdown from 'v-dropdown'
// or
// import { Dropdown } from 'v-dropdown'
function change (val) {
  console.log(val)
}
</script>
<template>
  <Dropdown @visible-change="change">
    <!-- trigger element -->
    <template #trigger>
      <button type="button">Click me</button>
    </template>

    <!-- contents display in dropdown -->
    <div>
      some contents
    </div>
  </Dropdown>
</template>

<script setup>
import Dropdown from 'v-dropdown'
// or
// import { Dropdown } from 'v-dropdown'
function change (val) {
  console.log(val)
}
</script>

Examples

Quick demo

html
<Dropdown>
  <!-- trigger element -->
  <template #trigger>
    <button type="button">Click me</button>
  </template>
  <!-- contents display in dropdown -->
  <div>some contents</div>
</Dropdown>
<Dropdown>
  <!-- trigger element -->
  <template #trigger>
    <button type="button">Click me</button>
  </template>
  <!-- contents display in dropdown -->
  <div>some contents</div>
</Dropdown>

Dropdown component uses click-triggered objects by default to open the dropdown conatiner

trigger by hover

html
<Dropdown trigger="hover">
  <template #trigger>
    <button type="button">Hover me</button>
  </template>
  ...
</Dropdown>
<Dropdown trigger="hover">
  <template #trigger>
    <button type="button">Hover me</button>
  </template>
  ...
</Dropdown>

trigger by contextmenu

html
<Dropdown
  trigger="contextmenu"
  :full-width="true"
>
  <template #trigger>
    <div>Mouse right click me</div>
  </template>
  ...
</Dropdown>
<Dropdown
  trigger="contextmenu"
  :full-width="true"
>
  <template #trigger>
    <div>Mouse right click me</div>
  </template>
  ...
</Dropdown>

Mouse right click trigger container area to open dropdown container

Mouse right click me

close toggle

html
<Dropdown :toggle="false" >
  ...
</Dropdown>
<Dropdown :toggle="false" >
  ...
</Dropdown>

Set the click to trigger the object cycle to switch the dropdown container open and closed, the effect also works on the mouse hover and the right mouse button menu trigger mode

Disabled

html
<Dropdown :disabled="true" >
  <!-- named scoped slots -->
  <template #trigger="{ visible, disabled }">
    <button
      type="button"
      :class="{
        'border-primary': visible.value,
        'bg-primary': visible.value,
        'bg-opacity-10': visible.value,
      }"
    >
      Click me (visible: {{ visible }}, disabled: {{ disabled }})
    </button>
  </template>
</Dropdown>
<Dropdown :disabled="true" >
  <!-- named scoped slots -->
  <template #trigger="{ visible, disabled }">
    <button
      type="button"
      :class="{
        'border-primary': visible.value,
        'bg-primary': visible.value,
        'bg-opacity-10': visible.value,
      }"
    >
      Click me (visible: {{ visible }}, disabled: {{ disabled }})
    </button>
  </template>
</Dropdown>

Manual

vue
<template>
  <Dropdown
    :manual="true"
    ref="dropdownManual"
  >
    <template #trigger>
      <input
        type="text"
        @input="inputChange"
      />
    </template>
    ...
  </Dropdown>
</template>

<script setup>
import { ref } from 'vue'
const dropdownManual = ref(null)

function inputChange (e) {
  if (e.target.value === '3') {
    dropdownManual.value.display()
  } else {
    // Dropdown expose `visible` state
    if (dropdownManual.value.visible) {
      dropdownManual.value.close()
    }
  }
}
</script>
<template>
  <Dropdown
    :manual="true"
    ref="dropdownManual"
  >
    <template #trigger>
      <input
        type="text"
        @input="inputChange"
      />
    </template>
    ...
  </Dropdown>
</template>

<script setup>
import { ref } from 'vue'
const dropdownManual = ref(null)

function inputChange (e) {
  if (e.target.value === '3') {
    dropdownManual.value.display()
  } else {
    // Dropdown expose `visible` state
    if (dropdownManual.value.visible) {
      dropdownManual.value.close()
    }
  }
}
</script>

In this example, the dropdown container will only open when the number 3 is entered

No border

html
<Dropdown :border="false" >
  ...
</Dropdown>
<Dropdown :border="false" >
  ...
</Dropdown>

Alignment direction

html
<Dropdown align="center" >
  ...
</Dropdown>
<Dropdown align="center" >
  ...
</Dropdown>

Specify container width

html
<Dropdown :width="500" >
  ...
</Dropdown>
<Dropdown :width="500" >
  ...
</Dropdown>

Slots

In the Dropdown component, the trigger object and content are distributed using slots

trigger named scoped slots

Named scoped slots for placing trigger objects, which outputs the following component state

ts
interface TriggerSlotData {
  visible: boolean  // the dropdown container visible status
  disabled: boolean // disabled status
}
interface TriggerSlotData {
  visible: boolean  // the dropdown container visible status
  disabled: boolean // disabled status
}
vue
<template>
  <Dropdown>
    <template #trigger> 
      <button type="button">Click me</button>
    </template>
  </Dropdown>
</template>
<template>
  <Dropdown>
    <template #trigger> 
      <button type="button">Click me</button>
    </template>
  </Dropdown>
</template>

Apply scoped slots status data

vue
<template>
  <Dropdown>
    <template #trigger="{ visible }">
      <button
        type="button"
        :class="{ active: visible }"
      >Click me</button>
    </template>
  </Dropdown>
</template>
<template>
  <Dropdown>
    <template #trigger="{ visible }">
      <button
        type="button"
        :class="{ active: visible }"
      >Click me</button>
    </template>
  </Dropdown>
</template>

default

The default slot is used to place the content area in the dropdown container

vue
<template>
  <Dropdown>
    <template #trigger>
      <button type="button">Click me</button>
    </template>

    <!-- contents display in dropdown default slot -->
    <div>                     
      some contents           
    </div>                    
  </Dropdown>
</template>
<template>
  <Dropdown>
    <template #trigger>
      <button type="button">Click me</button>
    </template>

    <!-- contents display in dropdown default slot -->
    <div>                     
      some contents           
    </div>                    
  </Dropdown>
</template>

Props

align

  • type 'left' | 'center' | 'right'
  • default 'left'

The dropdown container align to trigger container direction

TIP

Dropdown automatically determines the vertical orientation of the dropdown container (up or down) depending on the position of the screen

border

  • type boolean
  • default true

The dropdown container display border

toggle

  • type boolean
  • default true

Cyclically toggle the display/closing of the dropdown container

manual

  • type boolean
  • default false

Manual operation mode; when this mode is enabled, the trigger specified by trigger will no longer be able to open/close the drop-down bar, but can only be controlled by function calls, this mode is suitable for scenarios requiring precise control

disabled

  • type boolean
  • default false

Enabled / disabled Dropdown component

animated

  • type boolean | string
  • default true

To turn on/off the dropdown animation, in addition to setting on and off, you can also specify a string as the class name of the custom animation, the content of which needs to be defined externally

width

  • type number

Specify the width of the dropdown container, or adapt to the content width if not specified

fullWidth

  • type boolean
  • default false

Trigger container display mode

  • true block element box display: block
  • false inline element boxes display: inline-block

trigger

  • type 'click' | 'hover' | 'contextmenu'
  • default 'click'

Open the dropdown container trigger method

customTriggerClass

  • type string
  • default ''

Add custom class to trigger container

customContainerClass

  • type string
  • default ''

Add custom class to dropdown container

Events

Component operation response events

visible-change

Respond to the state change of the dropdown container opening / closing

ts
`visible-change`: (visible: boolean) => void
`visible-change`: (visible: boolean) => void

API

Before using component's API, need to declare a ref attribute for the component, declare a ref variable by ref() to hold the element reference(the name must match template ref value) and use it to call API methods

vue
<template>
  <Dropdown ref="dropdown" />
</template>

<script setup>
import { ref } from 'vue'
import { Dropdown } from 'v-dropdown'

const dropdown = ref(null)
// call api
dropdown.value.display()
</script>
<template>
  <Dropdown ref="dropdown" />
</template>

<script setup>
import { ref } from 'vue'
import { Dropdown } from 'v-dropdown'

const dropdown = ref(null)
// call api
dropdown.value.display()
</script>

display

Display dropdown container

ts
display: () => void
display: () => void

close

Close dropdown container

ts
close: () => void
close: () => void

toggleVisible

Toggle dropdown visible state

ts
toggleVisible: () => void
toggleVisible: () => void

adjust

Detect and adjust dropdown container position, make the dropdown container align to the trigger container

ts
adjust: () => void
adjust: () => void

Released under the MIT License.