Dropdown
Toggleable menu for displaying lists of links and actions.
| Name | Category | Description | Type | Default |
|---|---|---|---|---|
type | Style | Button type | ButtonType | — |
splitButton | Style | Whether to use split button | boolean | false |
maxHeight | Style | Max menu height, scrollable when exceeded | number | string | — |
showArrow | Style | Whether to show pixel arrow pointing to trigger | boolean | false |
hoverColor | Style | Custom hover background color for menu items | string | — |
DropdownItemdivided | Style | Whether to show divider | boolean | false |
size | Size | Button size | 'large' | 'default' | 'small' | 'default' |
disabled | State | Whether disabled | boolean | false |
DropdownItemdisabled | State | Whether disabled | boolean | false |
trigger | Behavior | Trigger mode | 'hover' | 'click' | 'contextmenu' | 'hover' |
hideOnClick | Behavior | Whether to hide menu on click | boolean | true |
placement | Behavior | Menu placement | Placement | 'bottom' |
↑ / ↓ | Behavior | Move focus between items (skip disabled) | — | |
Enter / Space | Behavior | Select the focused item | — | |
Escape | Behavior | Close menu and return focus to trigger | — | |
Home / End | Behavior | Jump to first/last enabled item | — | |
items | Content | Menu items | DropdownItemProps[] | — |
DropdownItemcommand | Content | Command | string | number | — |
DropdownItemlabel | Content | Display text | string | VNode | — |
DropdownItemicon | Content | Menu item icon name | string | — |
command | Event | Triggered when menu item is clicked | (command: string | number) => void | — |
visible-change | Event | Triggered when menu shows/hides | (visible: boolean) => void | — |
click | Event | Triggered when split button left side is clicked | (event: MouseEvent) => void | — |
default | Slot | Element that triggers dropdown | — | |
dropdown | Slot | Dropdown content, usually <px-dropdown-item> | — | |
open | Expose | Open dropdown | () => void | — |
close | Expose | Close dropdown | () => void | — |
Basic Usage
Hover on the dropdown menu to unfold it for more actions.
<template>
<px-dropdown :items="items" @command="handleCommand">
<px-button>
Dropdown Menu <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2', command: 'b' },
{ label: 'Action 3', command: 'c' },
{ label: 'Action 4', command: 'd', divided: true },
];
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Trigger
Configure click or hover to trigger.
<template>
<div class="demo-dropdown">
<px-dropdown :items="items" trigger="hover">
<px-button>Hover</px-button>
</px-dropdown>
<px-dropdown :items="items" trigger="click">
<px-button>Click</px-button>
</px-dropdown>
</div>
</template>
<script setup lang="ts">
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2', command: 'b' },
{ label: 'Action 3', command: 'c' },
];
</script>
<style scoped>
.demo-dropdown {
display: flex;
gap: 12px;
}
</style>Split Button
Use split-button to split the dropdown button.
<template>
<px-dropdown :items="items" split-button type="primary" trigger="click" @click="handleClick" @command="handleCommand">
Actions
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2', command: 'b' },
{ label: 'Action 3', command: 'c' },
];
const handleClick = () => {
PxMessage.info('Button clicked');
};
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Disabled Items
Use disabled attribute to disable certain items.
<template>
<px-dropdown :items="items" @command="handleCommand">
<px-button>
Dropdown <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2 (disabled)', command: 'b', disabled: true },
{ label: 'Action 3', command: 'c' },
{ label: 'Action 4 (disabled)', command: 'd', disabled: true },
];
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Icon Items
Use icon property on items to show pixel icons alongside labels.
<template>
<px-dropdown :items="items" @command="handleCommand">
<px-button>
Icon Menu <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Edit', command: 'edit', icon: 'edit' },
{ label: 'Search', command: 'search', icon: 'search' },
{ label: 'Bookmark', command: 'bookmark', icon: 'bookmark' },
{ label: 'Delete', command: 'delete', icon: 'trash', divided: true },
];
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Max Height
Use max-height to limit the menu height when there are many items.
<template>
<px-dropdown :items="items" :max-height="200" @command="handleCommand">
<px-button>
Long Menu <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = Array.from({ length: 20 }, (_, i) => ({
label: `Action ${i + 1}`,
command: `action-${i + 1}`,
}));
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Arrow
Use show-arrow to display a pixel-art arrow pointing from the dropdown panel to the trigger.
<template>
<div style="display: flex; gap: 16px; flex-wrap: wrap">
<px-dropdown :items="items" show-arrow @command="handleCommand">
<px-button>
Bottom (default) <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
<px-dropdown :items="items" show-arrow placement="right" @command="handleCommand">
<px-button>
Right <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
<px-dropdown :items="items" show-arrow placement="top" @command="handleCommand">
<px-button>
Top <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</div>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2', command: 'b' },
{ label: 'Action 3', command: 'c' },
];
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Custom Hover Color
Use hover-color to customize the background color of menu items on hover.
<template>
<div style="display: flex; gap: 16px; flex-wrap: wrap">
<px-dropdown :items="items" hover-color="#22c55e" @command="handleCommand">
<px-button>
Green <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
<px-dropdown :items="items" hover-color="#ef4444" @command="handleCommand">
<px-button>
Red <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
<px-dropdown :items="items" hover-color="#f59e0b" @command="handleCommand">
<px-button>
Amber <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</div>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Action 1', command: 'a' },
{ label: 'Action 2', command: 'b' },
{ label: 'Action 3', command: 'c' },
{ label: 'Action 4', command: 'd', divided: true },
];
const handleCommand = (command: string) => {
PxMessage.info(`Command: ${command}`);
};
</script>Keyboard Navigation
The dropdown supports full keyboard navigation. Press Arrow keys to move between items, Enter to select, and Escape to close.
<template>
<px-dropdown :items="items" trigger="click" @command="handleCommand">
<px-button>
Click & Navigate <px-icon icon="chevron-down" style="margin-left: 4px" />
</px-button>
</px-dropdown>
</template>
<script setup lang="ts">
import { PxMessage } from 'sakana-element';
const items = [
{ label: 'Home', command: 'home', icon: 'home' },
{ label: 'Edit', command: 'edit', icon: 'edit' },
{ label: 'Disabled', command: 'disabled', disabled: true },
{ label: 'Search', command: 'search', icon: 'search' },
{ label: 'Settings', command: 'settings', icon: 'sliders', divided: true },
];
const handleCommand = (command: string) => {
PxMessage.info(`Selected: ${command}`);
};
</script>