Overlay
DropdownMenu
Click-triggered dropdown menu with icons, keyboard shortcuts, checkbox/radio items, submenus, and custom rendering.
Basic Usage
<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>Keyboard Shortcuts
<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
Grid: On · Rulers: Off
<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
<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>Submenu
<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
<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
<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
| Slot | Description |
|---|---|
content | Main dropdown content |
arrow | Arrow element |
group | Item group container |
separator | Separator |
label | Group label |
item | Menu item |
itemLeadingIcon | Icon before label |
itemLabel | Label text |
itemTrailingKbds | Keyboard shortcuts area |
itemIndicator | Checkbox/radio indicator |
subTrigger | Submenu trigger |
subContent | Submenu content |
Snippets
| Snippet | Description |
|---|---|
children | Trigger element (receives open) |
header | Custom header (receives close) |
footer | Custom footer (receives close) |
item | Custom item |
content | Replace entire items rendering |
Props
| Prop | Type | Default |
|---|---|---|
items | DropdownMenuItem[] | - |
radioGroups | RadioGroup[] | - |
size | 'xs'|'sm'|'md'|'lg'|'xl' | 'md' |
arrow | boolean | ArrowProps | false |
transition | boolean | true |
portal | boolean | true |
open | boolean | false |
side | 'top'|'right'|'bottom'|'left' | 'bottom' |
align | 'start'|'center'|'end' | 'start' |
ref | HTMLElement | null | null |
class | string | - |
ui | Record<Slot, Class> | - |