Dropdown Menu
A neo-brutalist style dropdown menu built on reka-ui's DropdownMenu primitive, supporting menu items, checkboxes, radio groups, submenus, and keyboard shortcuts.
Demo
Installation
pnpm dlx brutx-vue@latest add dropdown-menuUsage
Basic Usage
<script setup>
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuLabel,
DropdownMenuShortcut,
} from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Log out</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</template>Checkbox Items
Use v-model to bind checkbox state, supporting both boolean and 'indeterminate' values.
<script setup>
import { ref } from 'vue'
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuCheckboxItem,
} from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
const showStatusBar = ref(true)
const showActivityBar = ref(false)
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline">View</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuCheckboxItem v-model="showStatusBar">
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem v-model="showActivityBar">
Activity Bar
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
</template>Radio Items
<script setup>
import { ref } from 'vue'
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuRadioItem,
DropdownMenuRadioGroup,
} from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
const position = ref('bottom')
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline">Position</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuRadioGroup v-model="position">
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="left">Left</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
</template>Submenus
<script setup>
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
} from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="outline">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>New Tab</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>More Tools</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Save Page</DropdownMenuItem>
<DropdownMenuItem>Developer Tools</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuContent>
</DropdownMenu>
</template>Sub-components
| Component | Description |
|---|---|
DropdownMenu | Root component, re-export of reka-ui DropdownMenuRoot |
DropdownMenuTrigger | Button to open the menu, re-export of reka-ui |
DropdownMenuContent | Dropdown content panel |
DropdownMenuItem | Standard menu item |
DropdownMenuCheckboxItem | Checkbox menu item |
DropdownMenuRadioItem | Radio menu item |
DropdownMenuRadioGroup | Radio item group, re-export of reka-ui |
DropdownMenuLabel | Section label |
DropdownMenuSeparator | Visual separator |
DropdownMenuShortcut | Keyboard shortcut hint |
DropdownMenuSub | Submenu container, re-export of reka-ui |
DropdownMenuSubTrigger | Submenu trigger |
DropdownMenuSubContent | Submenu content |
DropdownMenuGroup | Menu item group, re-export of reka-ui |
API Reference
DropdownMenuContent
| Name | Type | Default | Description |
|---|---|---|---|
sideOffset | number | undefined | 6 | Sets the pixel offset between the content panel and its trigger. |
DetailsDeclared typenumber | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuContent.vue | |||
align | "center" | "start" | "end" | undefined | undefined | Sets the horizontal alignment of the content panel relative to its trigger. |
DetailsDeclared type"center" | "start" | "end" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuContent.vue | |||
to | string | HTMLElement | undefined | undefined | Sets the selector or element used as the teleport target for the popup; it defaults to body. |
DetailsDeclared typestring | HTMLElement | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuContent.vue | |||
class | string | undefined | undefined | CSS classes added to the dropdown menu content panel. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuContent.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | Menu content such as items, labels, separators, or submenus. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuContent.vue | ||
DropdownMenuCheckboxItem
| Name | Type | Default | Description |
|---|---|---|---|
modelValue | boolean | "indeterminate" | undefined | undefined | The controlled checked state of the checkbox item, including indeterminate; synchronize it with update:modelValue. |
DetailsDeclared typeboolean | "indeterminate" | undefined Literal values
Default value details
SourceDropdownMenuCheckboxItem.vue:13 packages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | |||
defaultChecked | boolean | "indeterminate" | undefined | false | The initial checked state used when modelValue is not provided. |
DetailsDeclared typeboolean | "indeterminate" | undefined Literal values
Default value details
SourceDropdownMenuCheckboxItem.vue:15 packages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | |||
class | string | undefined | undefined | CSS classes added to the checkbox menu item root. |
DetailsDeclared typestring | undefined Default value details
SourceDropdownMenuCheckboxItem.vue:16 packages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | |||
iconSize | IconSize | undefined | "md" | Sets the size of the checked-state indicator icon. |
DetailsDeclared typeIconSize | undefined Literal values
Referenced types IconSize Type definition — IconSizeexport type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']> Default value details
SourceDropdownMenuCheckboxItem.vue:17 packages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@update:modelValue | [value: boolean | "indeterminate"] | Emits the new checkbox state when it changes: true, false, or indeterminate. |
DetailsDeclared type[value: boolean | "indeterminate"] Literal values
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | ||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The checkbox menu item’s label and other content. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuCheckboxItem.vue | ||
DropdownMenuItem
| Name | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | false | Adds indentation to align the item with icon-bearing items or submenu triggers. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | |||
disabled | boolean | undefined | false | Prevents the user from selecting this menu item. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | |||
textValue | string | undefined | undefined | Sets the text used for keyboard typeahead, especially when the item’s text cannot be inferred from its content. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | |||
closeOnSelect | boolean | undefined | undefined | Controls whether selecting this item closes the menu. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | |||
class | string | undefined | undefined | CSS classes added to the menu item root. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The menu item label and any optional icon or shortcut hint. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuItem.vue | ||
DropdownMenuLabel
| Name | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | — | Adds indentation to align the menu label with menu item content. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuLabel.vue | |||
class | string | undefined | — | CSS classes added to the menu label element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuLabel.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The heading for a menu group or menu content. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuLabel.vue | ||
DropdownMenuRadioItem
| Name | Type | Default | Description |
|---|---|---|---|
valueRequired | string | — | The string value represented by this radio item in its RadioGroup. |
DetailsDeclared typestring Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuRadioItem.vue | |||
class | string | undefined | — | CSS classes added to the radio menu item root. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuRadioItem.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The radio menu item’s label and optional content. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuRadioItem.vue | ||
DropdownMenuSeparator
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | — | CSS classes added to the menu separator element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSeparator.vue | |||
DropdownMenuShortcut
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | — | CSS classes added to the keyboard shortcut hint element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuShortcut.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The keyboard shortcut text or symbols to display. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuShortcut.vue | ||
DropdownMenuSubContent
| Name | Type | Default | Description |
|---|---|---|---|
sideOffset | number | undefined | 6 | Sets the pixel offset between the submenu panel and its trigger. |
DetailsDeclared typenumber | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubContent.vue | |||
class | string | undefined | undefined | CSS classes added to the submenu content panel. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubContent.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | Menu items and grouped content inside the submenu. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubContent.vue | ||
DropdownMenuSubTrigger
| Name | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | false | Adds indentation to align the submenu trigger with sibling menu items. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubTrigger.vue | |||
disabled | boolean | undefined | false | Prevents this submenu from opening. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubTrigger.vue | |||
class | string | undefined | undefined | CSS classes added to the submenu trigger root. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubTrigger.vue | |||
iconSize | IconSize | undefined | "md" | Sets the size of the icon indicating the submenu direction. |
DetailsDeclared typeIconSize | undefined Literal values
Referenced types IconSize Type definition — IconSizeexport type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']> Default value details
Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubTrigger.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The label content displayed by the submenu trigger. |
DetailsDeclared type{}Sourcepackages/ui/src/components/dropdown-menu/DropdownMenuSubTrigger.vue | ||
Accessibility
- Keyboard: Supports
Space/Enterto open the menu,Escapeto close the menu, arrow keys to navigate menu items - ARIA Attributes: Automatically manages
aria-expanded,aria-haspopup,role="menu"and other accessibility attributes - Focus Management: Focus is trapped within the menu when open; focus returns to the trigger when closed
- Submenu Navigation: Supports expanding and navigating submenus via arrow keys