<BaseDropdown /> · An options or a contextual menu.
<template>
<BaseDropdown variant="default" label="Default dropdown">
<BaseDropdownItem>Leads</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Reports</BaseDropdownItem>
<BaseDropdownItem>
Settings
<template #end>
<BaseKbd size="sm">
<span class="text-xs font-mono">⌘</span>
</BaseKbd>
<BaseKbd size="sm">
<span class="text-xs font-mono px-0.5">P</span>
</BaseKbd>
</template>
</BaseDropdownItem>
</BaseDropdown>
</template>
This component has optional sub components that you can use to create your dropdown menu. You can customize the dropdown's visual style by using the available props.
<template>
<BaseDropdown>
<BaseDropdownLabel>
<!-- Label goes here -->
</BaseDropdownLabel>
<!-- Sub dropdown -->
<BaseDropdownSub>
<template #title>
<!-- Sub dropdown title goes here -->
</template>
<BaseDropdownLabel>
<!-- Sub dropdown label goes here -->
</BaseDropdownLabel>
<BaseDropdownItem>
<!-- Sub dropdown item content goes here -->
</BaseDropdownItem>
</BaseDropdownSub>
<!-- Separator item -->
<BaseDropdownSeparator />
<BaseDropdownItem>
<!-- Item content goes here -->
</BaseDropdownItem>
<!-- Checkbox item -->
<BaseDropdownCheckbox />
<!-- Radio group -->
<BaseDropdownRadioGroup>
<!-- Radio item -->
<BaseDropdownRadio />
</BaseDropdownRadioGroup>
<!-- Menu top arrow -->
<BaseDropdownArrow />
</BaseDropdown>
</template>
This component has props that you can use to modify its visual style.
| Prop | Type |
|---|---|
labeldefault: "" | stringThe label to display for the dropdown. |
disableddefault: - | booleanDisables the dropdown. |
variantdefault: "default" | "default" | "primary" | "none" | "muted"The variant of the dropdown content |
roundeddefault: "md" | "none" | "md" | "sm" | "lg" | "full"The radius of the dropdown button. |
bindingsdefault: {} | { content?: DropdownMenuContentProps; trigger?: DropdownMenuTriggerProps; portal?: DropdownMenuPortalProps; }Optional bindings to pass to the inner components. |
classesdefault: {} | { content?: string | string[]; }Optional classes to pass to the inner components. |
default-opendefault: - | booleanThe open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. |
opendefault: - | booleanThe controlled open state of the menu. Can be used as `v-model:open`. |
dirdefault: - | Direction_3The reading direction of the combobox when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
modaldefault: - | booleanThe modality of the dropdown menu. When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. |
| Event | Emitted Value Type |
|---|---|
update:open | [payload: boolean] |
| Slot | Type |
|---|---|
#default | any |
#button | any |
#label | any |
| Prop | Type |
|---|---|
titledefault: "" | stringThe title to display for the dropdown item. |
textdefault: "" | stringThe text to display for the dropdown item. |
variantdefault: - | "default" | "primary" | "none" | "muted"The hover color of the dropdown-item inner elements. |
roundeddefault: - | "none" | "md" | "sm" | "lg" | "full"The radius of the dropdown-item. |
disableddefault: - | booleanWhen `true`, prevents the user from interacting with the item. |
text-valuedefault: - | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. <br> Use this when the content is complex, or you have non-textual content inside. |
as-childdefault: - | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
asdefault: - | AsTag | ComponentThe element or component this component should render as. Can be overwritten by `asChild`. |
| Event | Emitted Value Type |
|---|---|
select | [event: Event] |
| Slot | Type |
|---|---|
#default | any |
#title | any |
#text | any |
#start | any |
#end | any |
| Prop | Type |
|---|---|
titledefault: - | stringThe title to display for the dropdown item. |
textdefault: - | stringThe text to display for the dropdown item. |
variantdefault: - | "default" | "primary" | "none" | "muted"The variant of the dropdown content |
roundeddefault: - | "none" | "md" | "sm" | "lg" | "full"The radius of the dropdown button. |
bindingsdefault: - | { trigger?: DropdownMenuSubTriggerProps; content?: DropdownMenuSubContentProps; portal?: DropdownMenuPortalProps; }Optional bindings to pass to the inner components. |
default-opendefault: - | booleanThe open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. |
opendefault: - | booleanThe controlled open state of the menu. Can be used as `v-model:open`. |
| Event | Emitted Value Type |
|---|---|
update:open | [payload: boolean] |
| Slot | Type |
|---|---|
#default | any |
#title | any |
#text | any |
| Model | Type |
|---|---|
model-value | CheckedStateThe controlled checked state of the item. Can be used as `v-model`. |
| Prop | Type |
|---|---|
titledefault: "" | stringThe title to display for the dropdown item. |
textdefault: "" | stringThe text to display for the dropdown item. |
variantdefault: - | "default" | "primary" | "none" | "muted"The hover color of the dropdown-item inner elements. |
roundeddefault: - | "none" | "md" | "sm" | "lg"The radius of the dropdown-item. |
bindingsdefault: {} | { indicator?: DropdownMenuItemIndicatorProps; }Optional bindings to pass to the inner components. |
disableddefault: - | booleanWhen `true`, prevents the user from interacting with the item. |
text-valuedefault: - | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. <br> Use this when the content is complex, or you have non-textual content inside. |
as-childdefault: - | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
asdefault: - | AsTag | ComponentThe element or component this component should render as. Can be overwritten by `asChild`. |
| Event | Emitted Value Type |
|---|---|
select | [event: Event] |
| Slot | Type |
|---|---|
#default | any |
#title | any |
#text | any |
#end | any |
| Model | Type |
|---|---|
model-value | stringThe value of the selected item in the group. |
| Prop | Type |
|---|---|
as-childdefault: - | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
asdefault: - | AsTag | ComponentThe element or component this component should render as. Can be overwritten by `asChild`. |
| Slot | Type |
|---|---|
#default | any |
| Prop | Type |
|---|---|
titledefault: - | stringThe title to display for the dropdown item. |
textdefault: - | stringThe text to display for the dropdown item. |
variantdefault: - | "default" | "primary" | "none" | "muted"The hover color of the dropdown-item inner elements. |
roundeddefault: - | "none" | "md" | "sm" | "lg"The radius of the dropdown-item. |
bindingsdefault: {} | { indicator?: DropdownMenuItemIndicatorProps; }Optional bindings to pass to the inner components. |
valuedefault: - | stringThe unique value of the item. |
disableddefault: - | booleanWhen `true`, prevents the user from interacting with the item. |
text-valuedefault: - | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. <br> Use this when the content is complex, or you have non-textual content inside. |
as-childdefault: - | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
asdefault: - | AsTag | ComponentThe element or component this component should render as. Can be overwritten by `asChild`. |
| Event | Emitted Value Type |
|---|---|
select | [event: Event] |
| Slot | Type |
|---|---|
#default | any |
#text | any |
#end | any |
| Prop | Type |
|---|---|
as-childdefault: - | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
asdefault: - | AsTag | ComponentThe element or component this component should render as. Can be overwritten by `asChild`. |
Your can override the component default CSS variables in your main.css file.
@theme {
/* Default dropdown menu variables */
--color-portal-default-bg: var(--color-white);
--color-portal-default-border: var(--color-muted-300);
--color-portal-default-item-bg-active: var(--color-muted-100);
--color-portal-default-item-text: var(--color-input-default-text);
--color-portal-default-item-text-active: var(--color-primary-base);
/* Muted dropdown menu variables */
--color-portal-muted-bg: var(--color-muted-50);
--color-portal-muted-border: var(--color-muted-300);
--color-portal-muted-item-bg-active: var(--color-muted-200);
--color-portal-muted-item-text: var(--color-input-muted-text);
--color-portal-muted-item-text-active: var(--color-primary-base);
}
Use the variant prop to control the colors of the dropdown menu.
<template>
<BaseDropdown variant="primary" label="Primary dropdown">
<BaseDropdownItem>Leads</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Reports</BaseDropdownItem>
<BaseDropdownItem>
Settings
<template #end>
<BaseKbd size="sm">
<span class="text-xs font-mono">⌘</span>
</BaseKbd>
<BaseKbd size="sm">
<span class="text-xs font-mono px-0.5">P</span>
</BaseKbd>
</template>
</BaseDropdownItem>
</BaseDropdown>
</template>
You can nest other dropdowns inside a dropdown item, as well as checkboxes and radio buttons.
<script setup lang="ts">
const checkedOne = ref(false)
const checkedTwo = ref(false)
const selection = ref('first')
</script>
<template>
<div class="flex w-full justify-start gap-8">
<BaseDropdown label="Inner Submenus">
<BaseDropdownLabel>Label</BaseDropdownLabel>
<BaseDropdownSub>
<template #title>
Profile
</template>
<BaseDropdownLabel>Label</BaseDropdownLabel>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>General</BaseDropdownItem>
<BaseDropdownItem>Billing</BaseDropdownItem>
<BaseDropdownItem>Support</BaseDropdownItem>
</BaseDropdownSub>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownSub>
<template #title>
Settings
</template>
<BaseDropdownLabel>Label</BaseDropdownLabel>
<BaseDropdownItem>General</BaseDropdownItem>
<BaseDropdownItem>Users</BaseDropdownItem>
<BaseDropdownItem>Permissions</BaseDropdownItem>
<BaseDropdownItem>Security</BaseDropdownItem>
</BaseDropdownSub>
</BaseDropdown>
<BaseDropdown label="Radio">
<BaseDropdownRadioGroup v-model="selection">
<BaseDropdownRadioItem value="first">
First
<template #end>
<div class="flex gap-0.5">
<BaseKbd variant="default" size="sm">
alt
</BaseKbd>
<BaseKbd variant="default" size="sm">
1
</BaseKbd>
</div>
</template>
</BaseDropdownRadioItem>
<BaseDropdownRadioItem value="second">
Second
<template #end>
<div class="flex gap-0.5">
<BaseKbd variant="default" size="sm">
alt
</BaseKbd>
<BaseKbd variant="default" size="sm">
2
</BaseKbd>
</div>
</template>
</BaseDropdownRadioItem>
<BaseDropdownRadioItem value="third">
Third
<template #end>
<div class="flex gap-0.5">
<BaseKbd variant="default" size="sm">
alt
</BaseKbd>
<BaseKbd variant="default" size="sm">
3
</BaseKbd>
</div>
</template>
</BaseDropdownRadioItem>
</BaseDropdownRadioGroup>
</BaseDropdown>
<BaseDropdown label="Checkbox">
<BaseDropdownCheckbox
v-model="checkedOne"
title="Profile"
/>
<BaseDropdownCheckbox
title="Projects"
disabled
/>
<BaseDropdownCheckbox
v-model="checkedTwo"
title="Team"
/>
</BaseDropdown>
</div>
</template>
Use the spacing and arrow options to control the dropdown's position.
<template>
<BaseDropdown
label="Default spacing"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
<BaseDropdown
label="With top arrow"
:bindings="{ content: { sideOffset: 0 } }"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
<BaseDropdownArrow />
</BaseDropdown>
<BaseDropdown
label="With more spacing"
:bindings="{ content: { sideOffset: 10 } }"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
</template>
Use the DropdownLabel component to add a label to the dropdown menu. Mix and match with different options to create a unique dropdown.
<template>
<BaseDropdown header-label="My Team" variant="button" label="Dropdown" orientation="start">
<BaseDropdownItem to="#" title="Lana Jensen" text="Software Engineer" color="default" rounded="sm">
<template #start>
<BaseAvatar src="/img/avatars/4.svg" size="xs" />
</template>
</BaseDropdownItem>
<BaseDropdownItem to="#" title="Shawn Miller" text="Product Manager" color="default" rounded="sm">
<template #start>
<BaseAvatar src="/img/avatars/3.svg" size="xs" />
</template>
</BaseDropdownItem>
<BaseDropdownItem to="#" title="John Marynski" text="Sales Manager" color="default" rounded="sm">
<template #start>
<BaseAvatar src="/img/avatars/18.svg" size="xs" />
</template>
</BaseDropdownItem>
<BaseDropdownSeparator />
<BaseDropdownItem to="#" title="Garry Porter" text="CEO - Founder" color="default" rounded="sm">
<template #start>
<BaseAvatar src="/img/avatars/6.svg" size="xs" />
</template>
</BaseDropdownItem>
</BaseDropdown>
</template>
Use the #button slot to customize the dropdown button.
<template>
<BaseDropdown
:bindings="{
content: {
sideOffset: 0,
},
}"
>
<template #button>
<BaseButton
variant="primary"
size="icon-sm"
rounded="full"
class="group"
>
<Icon name="ph:plus" class="block text-base transition-transform group-data-[state=open]:rotate-45" />
</BaseButton>
</template>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
<BaseDropdownArrow :width="16" :height="8" />
</BaseDropdown>
</template>
Use the :bindings prop to control the dropdown's content alignment.
<template>
<BaseDropdown
label="End align" :bindings="{
content: {
align: 'end',
sideOffset: 5,
},
}"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
</template>
Use the :bindings prop to control the popping side of the dropdown menu.
<template>
<BaseDropdown
label="End align" :bindings="{
content: {
align: 'end',
sideOffset: 5,
},
}"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
</template>
Use the #start slot to insert an icon inside a dropdown item.
<template>
<BaseDropdown label="Dropdown" rounded="md">
<BaseDropdownItem
title="Profile"
text="View your profile"
class="w-72"
>
<template #start>
<Icon name="solar:user-rounded-linear" class="me-2 block text-[1.15rem]" />
</template>
</BaseDropdownItem>
<BaseDropdownItem
title="Projects"
text="View your projects"
>
<template #start>
<Icon name="solar:case-linear" class="me-2 block text-[1.15rem]" />
</template>
</BaseDropdownItem>
<BaseDropdownItem
title="Team"
text="Manage your team"
>
<template #start>
<Icon name="solar:widget-3-linear" class="me-2 block text-[1.15rem]" />
</template>
</BaseDropdownItem>
<BaseDropdownSeparator />
<BaseDropdownItem
title="Settings"
text="Set your preferences"
>
<template #start>
<Icon name="solar:settings-linear" class="me-2 block text-[1.15rem]" />
</template>
</BaseDropdownItem>
</BaseDropdown>
</template>
Use the #start slot to insert an avatar inside a dropdown item.
<template>
<BaseDropdown label="Dropdown" rounded="md">
<BaseDropdownItem
title="Lana Jensen"
text="Software Engineer"
class="w-80"
>
<template #start>
<BaseAvatar
src="/img/people/36.jpg"
size="xs"
/>
</template>
</BaseDropdownItem>
<BaseDropdownItem
title="Shawn Miller"
text="Product Manager"
>
<template #start>
<BaseAvatar
src="/img/people/18.jpg"
size="xs"
/>
</template>
</BaseDropdownItem>
<BaseDropdownItem
title="John Marynski"
text="Sales Manager"
>
<template #start>
<BaseAvatar
src="/img/people/16.jpg"
size="xs"
/>
</template>
</BaseDropdownItem>
<BaseDropdownItem
title="Garry Porter"
text="CEO - Founder"
>
<template #start>
<BaseAvatar
src="/img/people/6.jpg"
size="xs"
/>
</template>
</BaseDropdownItem>
</BaseDropdown>
</template>
By disabling the portal mode, the dropdown will be rendered inside the component.
<template>
<BaseDropdown
label="Fixed position" :bindings="{
portal: {
disabled: true,
},
content: {
positionStrategy: 'fixed',
},
}"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
<BaseDropdown
label="Absolute position" :bindings="{
portal: {
disabled: true,
},
content: {
positionStrategy: 'absolute',
},
}"
>
<BaseDropdownItem>Profile</BaseDropdownItem>
<BaseDropdownItem>Projects</BaseDropdownItem>
<BaseDropdownItem>Team</BaseDropdownItem>
<BaseDropdownItem>Settings</BaseDropdownItem>
</BaseDropdown>
</template>