DropdownMenu
Display a floating menu of actions triggered by a button. Supports action items, checkbox items, radio groups, submenus, keyboard shortcuts, separators, and labels.
Playground
Experiment with different props in real-time.
Basic Usage
Pass an array of items with label and optional icon. The trigger is placed inside the children snippet.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
const items = [
{ label: 'Edit', icon: 'lucide:pencil' },
{ label: 'Duplicate', icon: 'lucide:copy' },
{ label: 'Archive', icon: 'lucide:archive' },
{ label: 'Delete', icon: 'lucide:trash-2', color: 'error' }
];
</script>
<DropdownMenu {items}>
<Button label="Actions" trailingIcon="lucide:chevron-down" />
</DropdownMenu>With Keyboard Shortcuts
Use the kbds prop on items to display keyboard shortcut hints.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
const items = [
{ label: 'Undo', icon: 'lucide:undo-2', kbds: ['meta', 'z'] },
{ label: 'Redo', icon: 'lucide:redo-2', kbds: ['meta', 'shift', 'z'] },
{ type: 'separator' },
{ label: 'Cut', icon: 'lucide:scissors', kbds: ['meta', 'x'] },
{ label: 'Copy', icon: 'lucide:copy', kbds: ['meta', 'c'] },
{ label: 'Paste', icon: 'lucide:clipboard', kbds: ['meta', 'v'] }
];
</script>
<DropdownMenu {items}>
<Button label="Edit" trailingIcon="lucide:chevron-down" />
</DropdownMenu>Checkbox Items
Set type: 'checkbox' on items to render toggleable checkboxes. Use onCheckedChange to update state.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
let showStatusBar = $state(true);
let showActivityBar = $state(false);
let showPanel = $state(true);
$effect(() => {
items = [
{ type: 'label', label: 'Appearance' },
{ type: 'separator' },
{ type: 'checkbox', label: 'Status Bar', checked: showStatusBar, onCheckedChange: (v) => showStatusBar = v },
{ type: 'checkbox', label: 'Activity Bar', checked: showActivityBar, onCheckedChange: (v) => showActivityBar = v },
{ type: 'checkbox', label: 'Panel', checked: showPanel, onCheckedChange: (v) => showPanel = v }
];
});
let items = $state([
{ type: 'label', label: 'Appearance' },
{ type: 'separator' },
{ type: 'checkbox', label: 'Status Bar', checked: showStatusBar, onCheckedChange: (v) => showStatusBar = v },
{ type: 'checkbox', label: 'Activity Bar', checked: showActivityBar, onCheckedChange: (v) => showActivityBar = v },
{ type: 'checkbox', label: 'Panel', checked: showPanel, onCheckedChange: (v) => showPanel = v }
]);
</script>
<DropdownMenu {items}>
<Button label="View" trailingIcon="lucide:chevron-down" />
</DropdownMenu>Radio Items
Use type: 'radio' items with the radioGroups prop for single-select groups.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
let theme = $state('system');
const items = [
{ type: 'label', label: 'Theme' },
{ type: 'separator' },
{ type: 'radio', label: 'Light', value: 'light' },
{ type: 'radio', label: 'Dark', value: 'dark' },
{ type: 'radio', label: 'System', value: 'system' }
];
const radioGroups = [
{
name: 'theme',
value: theme,
onValueChange: (v) => theme = v,
items: items.filter((i) => i.type === 'radio')
}
];
</script>
<DropdownMenu {items} {radioGroups}>
<Button label="Theme" trailingIcon="lucide:chevron-down" />
</DropdownMenu>With Separators & Labels
Use type: 'separator' and type: 'label' to organize items into logical groups.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
const items = [
{ type: 'label', label: 'My Account' },
{ type: 'separator' },
{ label: 'Profile', icon: 'lucide:user' },
{ label: 'Settings', icon: 'lucide:settings' },
{ type: 'separator' },
{ label: 'Team', icon: 'lucide:users' },
{ label: 'Invite Users', icon: 'lucide:user-plus' },
{ type: 'separator' },
{ label: 'Logout', icon: 'lucide:log-out', color: 'error' }
];
</script>
<DropdownMenu {items}>
<Button label="Account" trailingIcon="lucide:chevron-down" />
</DropdownMenu>Submenu
Use type: 'sub' with a nested items array to create flyout submenus.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
const items = [
{ label: 'New File', icon: 'lucide:file-plus' },
{ label: 'New Folder', icon: 'lucide:folder-plus' },
{ type: 'separator' },
{
type: 'sub',
label: 'Share',
icon: 'lucide:share-2',
items: [
{ label: 'Email', icon: 'lucide:mail' },
{ label: 'Message', icon: 'lucide:message-square' },
{ type: 'separator' },
{ label: 'More...', icon: 'lucide:more-horizontal' }
]
},
{ type: 'separator' },
{ label: 'Delete', icon: 'lucide:trash-2', color: 'error' }
];
</script>
<DropdownMenu {items}>
<Button label="File" trailingIcon="lucide:chevron-down" />
</DropdownMenu>Sizes
5 sizes from extra small to extra large.
<DropdownMenu {items} size="xs">...</DropdownMenu>
<DropdownMenu {items} size="sm">...</DropdownMenu>
<DropdownMenu {items} size="md">...</DropdownMenu>
<DropdownMenu {items} size="lg">...</DropdownMenu>
<DropdownMenu {items} size="xl">...</DropdownMenu>Disabled Items
Set disabled: true on individual items to prevent interaction.
<script lang="ts">
import { DropdownMenu, Button } from 'sv5ui';
const items = [
{ label: 'Edit', icon: 'lucide:pencil' },
{ label: 'Duplicate', icon: 'lucide:copy', disabled: true },
{ label: 'Archive', icon: 'lucide:archive', disabled: true },
{ label: 'Delete', icon: 'lucide:trash-2', color: 'error' }
];
</script>
<DropdownMenu {items}>
<Button label="Actions" trailingIcon="lucide:chevron-down" />
</DropdownMenu>UI Slots
Use the ui prop to override classes on specific internal elements of the DropdownMenu.
| Slot | Description |
|---|---|
content | The floating menu panel — controls background, border, shadow, and rounding |
group | Groups related menu items together — controls spacing between groups |
separator | Visual divider between groups — controls color and spacing |
label | Non-interactive heading within a group — controls font size, weight, color |
item | Individual menu item row — controls padding, hover state, cursor |
itemIcon | Icon element within a menu item — controls icon size and color |
itemLabel | Text label within a menu item — controls font size and color |
itemKbd | Keyboard shortcut badge — controls font, background, rounding |
itemIndicator | Indicator for checkbox/radio items — controls size and color |
subTrigger | Submenu trigger item — controls hover state and arrow indicator |
subTriggerIcon | Arrow icon on the submenu trigger — controls icon size and color |
subContent | Submenu floating panel — controls background, border, shadow |
checkboxIndicator | Checkbox check mark indicator — controls icon and color |
radioIndicator | Radio dot indicator — controls icon and color |
Snippets
Use Svelte 5 snippets to customize specific parts of the DropdownMenu.
| Snippet | Type | Description |
|---|---|---|
children | Snippet | Trigger element — clicking opens the dropdown |
content | Snippet | Custom dropdown content — replaces default item rendering |
header | Snippet | Custom header above the menu items |
footer | Snippet | Custom footer below the menu items |
item | Snippet | Custom renderer for individual menu items |
itemLeading | Snippet | Custom leading section of menu items |
itemLabel | Snippet | Custom label section of menu items |
itemTrailing | Snippet | Custom trailing section of menu items |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | |
items | DropdownMenuItem[] | [] | |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | |
arrow | boolean | false | |
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | |
sideOffset | number | 4 | |
align | 'start' | 'center' | 'end' | 'start' | |
loop | boolean | true | |
radioGroups | RadioGroup[] | [] | |
transition | boolean | true | |
portal | boolean | true | |
checkedIcon | string | 'lucide:check' | |
submenuIcon | string | 'lucide:chevron-right' | |
class | string | - | |
ui | Record<Slot, Class> | - |