Dropdown menu
Displays a list of selectable actions or links, commonly used for navigation or contextual actions. Uses a trigger element to display the menu.
Component
Props
| Props | Default | Type |
|---|---|---|
items | — | DropdownMenuItem[] |
hasShadow | true | boolean |
hasBorder | true | boolean |
trigger | Trigger.CLICK | Trigger |
disabled | false | boolean |
prefetchOn | PrefetchOn.VISIBILITY | PrefetchOnStrategy |
position | bottom-right | DropdownPosition |
positionXOffset | 0 | number |
positionYOffset | 8 | number |
positionClass | 'absolute right-0 mt-2 top-full' | string |
isRelative | true | boolean |
shouldTeleport | true | boolean |
nestedMenuGap | 8 | number |
zIndex | '50' | string |
isSticky | false | boolean |
Slots
| Name | Description |
|---|---|
items | Slot to insert the '<DropdownMenuItem />' components |
activator | Slot to insert in activator item (eg. ActionButton) |
<template>
<DropdownMenu
class="min-w-[200px]"
>
<template #items>
<DropdownMenuItem
v-for="(item, index) in items"
:key="index"
v-bind="item"
/>
</template>
<template #activator>
<ActionButton
text="Open dropdown"
styleType="neutral-filled"
/>
</template>
</DropdownMenu>
</template>
<script setup lang="ts">
const items = ref<DropdownMenuItem[]>([
{
text: "Item 1",
},
{
text: "Item 2",
},
{
text: "Item 3",
},
{
text: "Item 4",
icon: "mdi:folder-outline",
children: [
{
sectionTitle: true,
text: "Nested section",
icon: "mdi:shape-outline",
},
{
text: "Subitem 4.1",
},
{
text: "Subitem 4.2",
children: [
{ text: "Third level item 4.2.1" },
{ text: "Third level item 4.2.2" },
],
},
],
},
])
</script>
Components
| Name | Description |
|---|---|
<DropdownMenu> | The main container that wraps all DropdownMenuItem components |
<DropdownMenuItem> | Represents the single menu item. |
<DropdownMenuActions> | Acts as a container for all DropdownMenuActions components. It is not included by default within the DropdownMenu component and must be manually injected when customizing the dropdown's structure. |
<DropdownSectionItem> | Non-interactive section header used inside dropdown menus and dropdown selects. |
Usage
items
Sets the items that will be displayed in the dropdown menu. It is an alternative to using the slot <template #items>.
It can be used while not using the <template #items> slot.
<template>
<DropdownMenu
:items="exampleItems"
class="min-w-[200px]"
>
<template #activator>
<ActionButton
text="Open dropdown"
styleType="neutral-filled"
/>
</template>
</DropdownMenu>
</template>
<script setup lang="ts">
const exampleItems = ref<DropdownMenuItem[]>([
{
text: "Item 1",
},
{
text: "Item 2",
},
{
text: "Item 3",
},
{
text: "Item 4",
icon: "mdi:folder-outline",
children: [
{
sectionTitle: true,
text: "Nested section",
icon: "mdi:shape-outline",
},
{
text: "Subitem 4.1",
},
{
text: "Subitem 4.2",
children: [
{ text: "Third level item 4.2.1" },
{ text: "Third level item 4.2.2" },
],
},
],
},
])
</script>
TypeScript interface
interface DropdownMenuItem {
actionType?: DropdownActionType
sectionTitle?: boolean
text?: string
icon?: any
size?: DropdownItemSize
type?: DropdownItemType
checked?: boolean
steps?: StepSwitchOption[]
stepValue?: string | number
userDisplayName?: string
userProfileImg?: string
imgUrl?: string
alt?: string
helpText?: string
to?: string
isExternal?: boolean
hasSeparator?: boolean
disabled?: boolean
callback?: (checked?: boolean) => void
stepCallback?: (value: string | number) => void
children?: DropdownMenuItem[]
}
Nested Items: Supports contextual nested dropdown menus up to 3 levels. Nested items are only available when using the :items prop with the fallback rendering mode. Items with children will automatically render as ACTION items (not links) with a right chevron indicator.
Nested items only work with the :items prop. When using the #items slot with DropdownMenuItem components directly, nesting is not supported.
hasShadow
Activates a dropdown shadow on the menu.
<template>
<DropdownMenu
hasShadow
>
....
</DropdownMenu>
</template>
hasBorder
Activates a border on the menu.
<template>
<DropdownMenu
hasBorder
>
....
</DropdownMenu>
</template>
trigger
Controls how the dropdown is opened from the activator.
<template>
<DropdownMenu
:trigger="Trigger.HOVER"
>
....
</DropdownMenu>
</template>
Options
| Value | Description |
|---|---|
CLICK | Opens and closes the dropdown on activator click. |
HOVER | Opens the dropdown on hover and closes when pointer leaves activator/dropdown. |
disabled
Disables the dropdown activator behavior. When true, click and hover triggers will not open the menu.
<template>
<DropdownMenu
:disabled="true"
>
....
</DropdownMenu>
</template>
prefetchOn
Controls when dropdown item route targets should be prefetched. It uses either the PrefetchOnStrategy type or the PrefetchOn enum.
<template>
<DropdownMenu
:items="exampleItems"
:prefetchOn="PrefetchOn.INTERACTION"
/>
</template>
Options
| Value | Description |
|---|---|
VISIBILITY | Prefetches routes based on visibility strategy. |
INTERACTION | Prefetches routes when users hover or focus a dropdown item with a route target. |
You can also pass an object strategy:
{
visibility: true,
interaction: true,
}
position
Sets the position of the dropdown menu relative to its activator. Uses the DropdownPosition enum.
Do not forget to adjust the X and Y offsets to achieve the desired positioning. It is particularly useful to set a gap between the dropdown menu and the activator.
<template>
<DropdownMenu
:position="DropdownPosition.BOTTOM_RIGHT"
>
....
</DropdownMenu>
</template>
Options
| Value | Description |
|---|---|
TOP_LEFT | Aligns the menu above and to the left of the activator. |
TOP_RIGHT | Aligns the menu above and to the right of the activator. |
BOTTOM_LEFT | Places the menu below and left-aligned with the activator. |
BOTTOM_RIGHT | Places the menu below and right-aligned with the activator. |
LEFT_TOP | Displays the menu to the left of the activator, aligned to its top edge. |
LEFT_BOTTOM | Displays the menu to the left of the activator, aligned to its bottom edge. |
RIGHT_TOP | Displays the menu to the right of the activator, aligned to its top edge. |
RIGHT_BOTTOM | Displays the menu to the right of the activator, aligned to its bottom edge. |
positionXOffset
Sets the horizontal offset of the dropdown menu relative to its activator. Positive values move the menu to the right, while negative values move it to the left.
<template>
<DropdownMenu
positionXOffset="10"
>
....
</DropdownMenu>
</template>
positionYOffset
Sets the vertical offset of the dropdown menu relative to its activator. Positive values move the menu down, while negative values move it up.
<template>
<DropdownMenu
positionYOffset="10"
>
....
</DropdownMenu>
</template>
positionClass
Applies Tailwind classes to control the dropdown menu's placement relative to its activator. Useful for fine-tuning alignment, spacing, or offset beyond default positioning.
When applying positionClass, position offsets and default positions will be ignored and it only works with teleport disabled (shouldTeleport=false).
<template>
<DropdownMenu
positionClass="absolute right-0 mt-2 top-full"
>
....
</DropdownMenu>
</template>
isRelative
Sets the dropdown menu wrapper as the relative element. In case relative is false, the dropdown menu will be positioned absolutely or will try to find the next parent relative element.
<template>
<DropdownMenu
isRelative
>
....
</DropdownMenu>
</template>
shouldTeleport
Determines whether the dropdown menu should be teleported to the end of the document body. This is useful for avoiding overflow issues within containers that have restricted dimensions or overflow settings.
<template>
<DropdownMenu
shouldTeleport="false"
>
....
</DropdownMenu>
</template>
nestedMenuGap
Sets the horizontal gap (in pixels) between a parent dropdown panel and its nested child panel.
<template>
<DropdownMenu
:items="exampleItems"
:nestedMenuGap="8"
/>
</template>
zIndex
Sets the CSS z-index property for the dropdown menu, controlling its stacking order relative to other elements on the page.
<template>
<DropdownMenu
zIndex="50"
>
....
</DropdownMenu>
</template>
isSticky
When true, the teleported dropdown panel uses position: fixed instead of position: absolute, anchoring it to the viewport rather than the document. Use this when the activator lives inside a sticky container (e.g. a sticky header) so the panel stays correctly positioned as the user scrolls.
<template>
<DropdownMenu
isSticky
>
....
</DropdownMenu>
</template>
DropdownMenuItem
<DropdownMenuItem> represents an individual item within the dropdown menu. It supports multiple visual and functional types, such as text, icons, user profiles, and images, making it flexible for various use cases like navigation, actions, or exporting data.
Props
| Props | Default | Type |
|---|---|---|
actionType | LINK | DropdownActionType |
text | Menu item text | string |
icon | mdi:help | string |
size | MD | DropdownItemSize |
type | TEXT | DropdownItemType |
checked | false | boolean |
steps | [] | StepSwitchOption[] |
stepValue | — | string | number |
userDisplayName | Test user | string |
userProfileImg | — | string |
imgUrl | — | string |
alt | Menu item image | string |
helpText | — | string |
to | / | string |
isExternal | false | boolean |
hasSeparator | false | boolean |
hasNestedLevels | false | boolean |
disabled | false | boolean |
prefetchOn | PrefetchOn.VISIBILITY | PrefetchOnStrategy |
actionType
Sets the action type for the menu item. Uses the DropdownActionType enum.
<template>
<DropdownMenuItem
actionType="action"
>
....
</DropdownMenuItem>
</template>
text
Sets the text content of the menu item.
<template>
<DropdownMenuItem
text="Menu item text"
>
....
</DropdownMenuItem>
</template>
icon
Sets the icon to be displayed in the menu item.
<template>
<DropdownMenuItem
icon="mdi:help"
>
....
</DropdownMenuItem>
</template>
size
Sets the size of the menu item. Uses the DropdownItemSize enum.
<template>
<DropdownMenuItem
size="DropdownItemSize.LG"
>
....
</DropdownMenuItem>
</template>
type
Sets the type of the menu item. Uses the DropdownItemType enum.
<template>
<DropdownMenuItem
type="DropdownItemType.TEXT"
>
....
</DropdownMenuItem>
</template>
Options
| Value | Description |
|---|---|
TEXT | Displays plain text. |
DANGER_TEXT | Displays text styled to indicate a destructive action. |
ICON | Displays an icon alongside the text. |
DANGER_ICON | Displays an icon styled to indicate a destructive action, alongside the text. |
USER | Displays a user avatar and display name instead of plain text. |
IMAGE | Displays an image alongside the text. |
CHECKBOX | Displays a non-interactive Checkbox reflecting the checked prop, aligned to the end of the item. |
SWITCH | Displays a non-interactive Switch reflecting the checked prop, aligned to the end of the item. |
CHECK | Displays a check icon reflecting the checked prop, aligned to the end of the item, when checked is true. |
STEP_SWITCH | Displays an interactive StepSwitch built from the steps prop and reflecting the stepValue prop, aligned to the end of the item. |
ICON_CHECKBOX | Displays a leading icon together with a non-interactive Checkbox reflecting the checked prop, aligned to the end of the item. |
ICON_SWITCH | Displays a leading icon together with a non-interactive Switch reflecting the checked prop, aligned to the end of the item. |
ICON_CHECK | Displays a leading icon together with a check icon reflecting the checked prop, aligned to the end of the item, when checked is true. |
ICON_STEP_SWITCH | Displays a leading icon together with an interactive StepSwitch built from the steps prop and reflecting the stepValue prop, aligned to the end of the item. |
checked
Sets the checked state of the control rendered when type is DropdownItemType.CHECKBOX, DropdownItemType.SWITCH, DropdownItemType.CHECK, DropdownItemType.ICON_CHECKBOX, DropdownItemType.ICON_SWITCH, or DropdownItemType.ICON_CHECK. Has no effect for other types.
Clicking anywhere on the menu item toggles the state automatically: it emits click and update:checked with the new boolean value, and, unlike other item types, does not close the dropdown, so multiple options can be toggled in the same session. Use v-model:checked for two-way binding, or handle update:checked manually.
Only a checked/unchecked boolean state is supported. An intermediate/indeterminate state is not considered for dropdown menu items.
<template>
<DropdownMenuItem
type="DropdownItemType.CHECKBOX"
text="Show hidden files"
v-model:checked="showHiddenFiles"
/>
</template>
<script setup lang="ts">
const showHiddenFiles = ref(false)
</script>
When using the items prop instead, the toggled value is passed as the first argument to the item's callback:
<template>
<DropdownMenu :items="items" />
</template>
<script setup lang="ts">
const showHiddenFiles = ref(false)
const items = computed<DropdownMenuItem[]>(() => [
{
text: 'Show hidden files',
type: DropdownItemType.CHECKBOX,
checked: showHiddenFiles.value,
callback: (checked) => { showHiddenFiles.value = checked ?? false },
},
])
</script>
steps
Sets the steps of the StepSwitch rendered when type is DropdownItemType.STEP_SWITCH or DropdownItemType.ICON_STEP_SWITCH. Has no effect for other types. See StepSwitch for the available options, such as the recommended maximum number of steps.
<template>
<DropdownMenuItem
:type="DropdownItemType.STEP_SWITCH"
text="Effort"
:steps="steps"
v-model:stepValue="effort"
/>
</template>
<script setup lang="ts">
const steps: StepSwitchOption[] = [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
]
const effort = ref<string | number>('medium')
</script>
TypeScript interface
interface StepSwitchOption {
value: string | number
label?: string
}
stepValue
Sets the selected step, by its value, of the StepSwitch rendered when type is DropdownItemType.STEP_SWITCH or DropdownItemType.ICON_STEP_SWITCH. Has no effect for other types.
Changing the step through the StepSwitch emits update:stepValue with the value of the new step. Unlike other item types, clicking the rest of the item does nothing and the dropdown is not closed. Use v-model:stepValue for two-way binding, or handle update:stepValue manually.
When using the items prop instead, the selected value is passed to the item's stepCallback:
<template>
<DropdownMenu :items="items" />
</template>
<script setup lang="ts">
const effort = ref<string | number>('medium')
const items = computed<DropdownMenuItem[]>(() => [
{
text: 'Effort',
type: DropdownItemType.STEP_SWITCH,
steps: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
],
stepValue: effort.value,
stepCallback: (value) => { effort.value = value },
},
])
</script>
userDisplayName
Sets the userDisplayName of the user profile.
<template>
<DropdownMenuItem
userDisplayName="Test user"
>
....
</DropdownMenuItem>
</template>
userProfileImg
Sets the URL of the user profile image.
<template>
<DropdownMenuItem
userProfileImg="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
>
....
</DropdownMenuItem>
</template>
imgUrl
Sets the URL of the image.
<template>
<DropdownMenuItem
imgUrl="https://www.wheeliebinstorage.co.uk/wp-content/uploads/2025/01/Small-Space-Garden-Ideas.jpg"
>
....
</DropdownMenuItem>
</template>
alt
Sets the alternative text for the image.
<template>
<DropdownMenuItem
alt="Menu item image"
>
....
</DropdownMenuItem>
</template>
helpText
Sets the help text for the menu item.
<template>
<DropdownMenuItem
helpText="Help text"
>
....
</DropdownMenuItem>
</template>
to
Sets the target URL for the menu item.
<template>
<DropdownMenuItem
to="/"
>
....
</DropdownMenuItem>
</template>
isExternal
Sets whether the menu item is external or not.
<template>
<DropdownMenuItem
isExternal
>
....
</DropdownMenuItem>
</template>
hasSeparator
Adds a separator line below the menu item.
<template>
<DropdownMenuItem
hasSeparator
>
....
</DropdownMenuItem>
</template>
hasNestedLevels
Shows a right chevron indicator for items that open nested levels. It is used by DropdownMenu fallback rendering for contextual menus.
<template>
<DropdownMenuItem
text="Has nested levels"
hasNestedLevels
/>
</template>
prefetchOn
Controls when the dropdown menu item route target should be prefetched. It uses either the PrefetchOnStrategy type or the PrefetchOn enum.
<template>
<DropdownMenuItem
text="Profile"
to="/profile"
:prefetchOn="PrefetchOn.INTERACTION"
/>
</template>
Options
| Value | Description |
|---|---|
VISIBILITY | Prefetches routes based on visibility strategy. |
INTERACTION | Prefetches routes when users hover or focus the item. |
You can also pass an object strategy:
{
visibility: true,
interaction: true,
}
disabled
Disables the menu item interaction and applies disabled visual styles.
<template>
<DropdownMenuItem
text="Disabled item"
:disabled="true"
/>
</template>