Dropdown
The Dropdown component consists of a trigger and a floating dropdown menu panel. Clicking or hovering over the trigger reveals the menu panel, which typically contains a set of action options. Common use‑cases include button dropdowns, navigation menus, table header dropdowns, "more‑actions" menus and multi‑level sub‑menus. Built on top of Tooltip.
Basic Usage
There are two ways to use Dropdown: Use options prop to render Dropdown menu items, or use slot#menu to customize menu with <re-dropdown-menu> and <re-dropdown-item>.
<template>
<re-dropdown :options="options" @select="select">
<re-button>
Dropdown Options List
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown @select="select">
<re-button>
Dropdown Items List
<arrow-downward class="ml-5px" />
</re-button>
<template #menu>
<re-dropdown-menu>
<re-dropdown-item value="item1" label="item-1"></re-dropdown-item>
<re-dropdown-item value="item2">Item 2</re-dropdown-item>
<re-dropdown-item value="item3">Item 3</re-dropdown-item>
</re-dropdown-menu>
</template>
</re-dropdown>
</template>
<script lang="ts" setup>
import {
ReDropdown,
ReDropdownMenu,
ReDropdownItem,
ReButton,
ReMessage,
ArrowDownward
} from 'rappel-ui'
const options = [
{ label: 'option1', value: 'option1' },
{ label: 'option2', value: 'option2' },
{ label: 'option3', value: 'option3' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Placement
<template>
<div class="max-w-600px mx-auto">
<div class="flex justify-center">
<re-dropdown placement="top-start" :options @select="select">
<re-button>top-start</re-button>
</re-dropdown>
<re-dropdown placement="top" :options @select="select">
<re-button>top</re-button>
</re-dropdown>
<re-dropdown placement="top-end" :options @select="select">
<re-button>top-end</re-button>
</re-dropdown>
</div>
<div class="flex justify-between">
<div class="flex flex-col items-start">
<re-dropdown placement="left-start" :options @select="select">
<re-button>left-start</re-button>
</re-dropdown>
<re-dropdown placement="left" :options @select="select">
<re-button class="mt-1em ml-0!">left</re-button>
</re-dropdown>
<re-dropdown placement="left-end" :options @select="select">
<re-button class="mt-1em ml-0!">left-end</re-button>
</re-dropdown>
</div>
<div class="flex flex-col items-end">
<re-dropdown placement="right-start" :options @select="select">
<re-button>right-start</re-button>
</re-dropdown>
<re-dropdown placement="right" :options @select="select">
<re-button class="mt-1em ml-0!">right</re-button>
</re-dropdown>
<re-dropdown placement="right-end" :options @select="select">
<re-button class="mt-1em ml-0!">right-end</re-button>
</re-dropdown>
</div>
</div>
<div class="flex justify-center">
<re-dropdown placement="bottom-start" :options @select="select">
<re-button>bottom-start</re-button>
</re-dropdown>
<re-dropdown placement="bottom" :options @select="select">
<re-button>bottom</re-button>
</re-dropdown>
<re-dropdown placement="bottom-end" :options @select="select">
<re-button>bottom-end</re-button>
</re-dropdown>
</div>
</div>
</template>
<script lang="ts" setup>
import { ReDropdown, ReButton, ReMessage } from 'rappel-ui'
const options = [
{ label: 'option1', value: 'option1' },
{ label: 'option2', value: 'option2' },
{ label: 'option3', value: 'option3' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Trigger
Use hover 、 click 、 focus and contextmenu to display Dropdown menu by trigger attribute.
<template>
<re-dropdown :options="options" trigger="hover" @select="select">
<re-button>
Hover me
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown :options="options" trigger="click" @select="select">
<re-button>
Click me
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown :options="options" trigger="focus" @select="select">
<re-button>
Focus me
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown :options="options" trigger="contextmenu" @select="select">
<re-button>
Contextmenu
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
</template>
<script lang="ts" setup>
import { ReDropdown, ReButton, ReMessage, ArrowDownward } from 'rappel-ui'
const options = [
{ label: 'option1', value: 'option1' },
{ label: 'option2', value: 'option2' },
{ label: 'option3', value: 'option3' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Disabled
The disabled attribute specifies whether the dropdown menu is disabled, disabled the Dropdown or the Dropdown menu items.
<template>
<re-dropdown :options="options" @select="select">
<re-button>
Disabled Dropdown Option
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown @select="select">
<re-button>
Disabled Dropdown Item
<arrow-downward class="ml-5px" />
</re-button>
<template #menu>
<re-dropdown-menu>
<re-dropdown-item value="item1">Item 1</re-dropdown-item>
<re-dropdown-item value="item2" disabled>Item 2</re-dropdown-item>
<re-dropdown-item value="item3">Item 3</re-dropdown-item>
</re-dropdown-menu>
</template>
</re-dropdown>
<re-dropdown :options="treeOptions" @select="select">
<re-button>
Disabled Submenu Option
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown @select="select">
<re-button>
Disabled Submenu Item
<arrow-downward class="ml-5px" />
</re-button>
<template #menu>
<re-dropdown-menu>
<re-dropdown-item value="Item 1">Item 1</re-dropdown-item>
<re-dropdown-item value="Item 2">Item 2</re-dropdown-item>
<re-dropdown-submenu disabled>
<template #label>Item 3</template>
<re-dropdown-item value="Item 3-1">Item 3-1</re-dropdown-item>
<re-dropdown-item value="Item 3-2">Item 3-2</re-dropdown-item>
</re-dropdown-submenu>
</re-dropdown-menu>
</template>
</re-dropdown>
<re-dropdown disabled :options="options" @select="select">
<re-button disabled>
Disabled Dropdown
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
</template>
<script lang="ts" setup>
import {
ReDropdown,
ReDropdownMenu,
ReDropdownItem,
ReDropdownSubmenu,
ReButton,
ReMessage,
ArrowDownward
} from 'rappel-ui'
const options = [
{ label: 'option1', value: 'option1' },
{ label: 'option2', value: 'option2', disabled: true },
{ label: 'option3', value: 'option3' }
]
const treeOptions = [
{ label: 'option1', value: 'option1' },
{
label: 'option2',
value: 'option2',
disabled: true,
children: [{ label: 'option2-1', value: 'option2-1' }]
},
{ label: 'option3', value: 'option3' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Tree
When you need a tree dropdown menu, options should be a tree-shaped array. You can also build a tree menu manually using <re-dropdown-menu>、<re-dropdown-submenu> and <re-dropdown-item> components.
<template>
<re-dropdown :options="options" @select="select">
<re-button>
Dropdown Options List
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown @select="select">
<re-button>
Dropdown Items List
<arrow-downward class="ml-5px" />
</re-button>
<template #menu>
<re-dropdown-menu>
<re-dropdown-item value="Item 1" label="Item 1"></re-dropdown-item>
<re-dropdown-item value="Item 2">Item 2</re-dropdown-item>
<re-dropdown-submenu>
<template #label>Item 3</template>
<re-dropdown-item value="Item 3-1">Item 3-1</re-dropdown-item>
<re-dropdown-item value="Item 3-2">Item 3-2</re-dropdown-item>
<re-dropdown-submenu>
<template #label>Item 3-3</template>
<re-dropdown-item value="Item 3-3-1">Item 3-3-1</re-dropdown-item>
<re-dropdown-item value="Item 3-3-2">Item 3-3-2</re-dropdown-item>
</re-dropdown-submenu>
</re-dropdown-submenu>
</re-dropdown-menu>
</template>
</re-dropdown>
</template>
<script lang="ts" setup>
import {
ReDropdown,
ReDropdownMenu,
ReDropdownSubmenu,
ReDropdownItem,
ReButton,
ReMessage,
ArrowDownward
} from 'rappel-ui'
const options = [
{
label: 'option1',
value: 'option1',
children: [
{
label: 'option1-1',
value: 'option1-1'
},
{
label: 'option1-2',
value: 'option1-2',
children: [{ label: 'option1-2-1', value: 'option1-2-1' }]
}
]
},
{ label: 'option2', value: 'option2' },
{ label: 'option3', value: 'option3' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Icon
Use icon prop to add an icon to the menu item. It accepts an icon name or a VNode component.
<template>
<re-dropdown :options="options" @select="select">
<re-button>
Dropdown Options List
<arrow-downward class="ml-5px" />
</re-button>
</re-dropdown>
<re-dropdown @select="select">
<re-button>
Dropdown Items List
<arrow-downward class="ml-5px" />
</re-button>
<template #menu>
<re-dropdown-menu>
<re-dropdown-item value="item1" label="item-1" :icon="Star"></re-dropdown-item>
<re-dropdown-item value="item2" icon="more-dot-circle-outline-horizontal">
Item 2
</re-dropdown-item>
<re-dropdown-item value="item3">
<Delete size="16" color="var(--re-color-danger-base)" class="mr-5px" />
<span>Item 3</span>
</re-dropdown-item>
</re-dropdown-menu>
</template>
</re-dropdown>
</template>
<script lang="ts" setup>
import { ReDropdown, ReDropdownMenu, ReDropdownItem, ReButton, ReMessage } from 'rappel-ui'
import { ArrowDownward, Star, Delete } from '@rappel-ui/svg-icons'
const options = [
{
label: 'option1',
value: 'option1',
icon: 'copy',
children: [
{ label: 'option1-1', value: 'option1-1', icon: 'check-circle' },
{ label: 'option1-2', value: 'option1-2', icon: 'delete' }
]
},
{ label: 'option2', value: 'option2', icon: 'exclam' },
{ label: 'option3', value: 'option3', icon: 'more-line' }
]
const select = (value: string) => {
ReMessage.success(`You selected ${value}`)
}
</script>Dropdown Attributes
| Name | Description | Type | Default |
|---|---|---|---|
| options | Data-driven rendering for Dropdown menu, accepts an array of menu items | Array<OptionsItem>: interface | [] |
| item-props | Field Names Mapping for options | interface | {label: 'label', value: 'value', disabled: 'disabled', children: 'children' } |
| close-on-select | Whether to close the dropdown menu when clicking a menu item | boolean | true |
| placement | Dropdown position | enum | bottom |
| trigger | The trigger event name | enum | hover |
| disabled | Whether Dropdown menu is disabled | boolean | — |
| visible / v-model:visible | Whether Dropdown is visible | boolean | — |
| offset | Offset from the reference edge. See Floating UI OffsetOptions for details | number | interface | 10 |
| width | Dropdown width | number | string | — |
| height | Dropdown height | number | string | — |
| max-width | Dropdown max width | number | string | — |
| max-height | Dropdown max height | number | string | — |
| theme | Dropdown theme | 'dark' |'light' | light |
| reverse-theme | whether to reverse Dropdown theme color | boolean | false |
| append-to | Target element for appending Dropdown | cssSelector | HTMLElement | body |
| teleported | Whether to teleport Dropdown to the appendTo target | boolean | true |
| persistent | Whether to keep the floating open on hover | boolean | true |
| click-to-toggle | Whether to toggle the floating on click, only trigger='click' | boolean | true |
| floating-class | Custom class for the floating | string | object | Array | — |
| floating-style | Custom style for the floating | string | object | Array | — |
| show-delay | Delay(ms) before Dropdown appears , but not effective when visible is present or is-virtual or is-external | number | 0 |
| hide-delay | Delay(ms) before Dropdown disappears , but not effective when visible is present or is-virtual or is-external | number | 200 |
| show-arrow | Whether to show arrow for Dropdown | boolean | true |
| arrow-size | The arrow size | number | 8 |
| arrow-offset | Padding between the arrow and the Dropdown edge | number | 4 |
| arrow-options | Floating UI ArrowOptions Parameters | interface | — |
| transition | Name of Vue3 Transition component | string | dropdown |
| css-transition | Css of Vue3 Transition component | boolean | true |
| strategy | The type of CSS position property to use | 'absolute' | 'fixed' | absolute |
| css-duration | Duration of Vue3 Transition component for fade in/fade out | number | 300 |
| boundary | Boundary of Floating UI DetectOverflowOptions : interface | union | clippingAncestors |
| alt-boundary | AltBoundary of Floating UI DetectOverflowOptions | boolean | false |
| root-boundary | RootBoundary of Floating UI DetectOverflowOptions | union | viewport |
| element-context | ElementContext of Floating UI DetectOverflowOptions | 'reference' | 'floating' | floating |
| flip-offset | Offset from boundary before flipping, Padding of Floating UI DetectOverflowOptions | union | 8 |
| flip-options | Floating UI FlipOptions Parameters | interface | — |
| inline-options | Floating UI InlineOptions Parameters | interface | — |
| is-external | Whether external reference is enabled | boolean | — |
| external-ref | External reference target | HTMLElement | — |
| is-virtual | Whether virtual reference is enabled | boolean | — |
| virtual-ref | Virtual reference object for Floating UI VirtualElement | interface | — |
Dropdown Events
| Name | Description | Parameters |
|---|---|---|
| select | Triggered when a menu item is clicked | Function |
| before-enter | Vue3 <Transition> event hook | Function |
| enter | Vue3 <Transition> event hook | Function |
| after-enter | Vue3 <Transition> event hook | Function |
| before-leave | Vue3 <Transition> event hook | Function |
| leave | Vue3 <Transition> event hook | Function |
| after-leave | Vue3 <Transition> event hook | Function |
| enter-cancelled | Vue3 <Transition> event hook | Function |
| leave-cancelled | Vue3 <Transition> event hook | Function |
Dropdown Slots
| Name | Description |
|---|---|
| default | Customize default reference |
| content | Customize default content |
Dropdown Exposes
| Name | Description | Type |
|---|---|---|
| update | Manually updates the Dropdown position | Function |
| show | Manually show the Dropdown | Function |
| hide | Manually hide the Dropdown | Function |
| triggerRef | The trigger refernce element | HTMLElement |
| floatingRef | The Dropdown layer element | HTMLElement |
| arrowRef | The Dropdown arrow element | HTMLElement |
