Dropdown
Dropdowns display contextual menus and option lists. They're perfect for navigation menus, action lists, and settings panels. Domma's dropdown supports positioning, triggers, and dynamic content.
Key Features
- Multiple Triggers - Click or hover activation
- Smart Positioning - Auto-adjusts to viewport edges
- Keyboard Navigation - Arrow keys and Enter/Escape support
- Close on Outside Click - Automatic dismiss behaviour
Basic Usage
// Attach to a button element
const dropdown = Domma.elements.dropdown('#my-button', {
items: [
{ text: 'Edit', value: 'edit' },
{ text: 'Delete', value: 'delete' }
],
trigger: 'click',
position: 'bottom-start',
onSelect: (item) => console.log(item.value)
});
Note: The dropdown component creates menus programmatically from the items
array.
It doesn't use static HTML menu structures.
Quick Start
Simple Dropdown
<button class="btn btn-primary" id="my-dropdown">Actions</button>
<script>
Domma.elements.dropdown('#my-dropdown', {
items: [
{ text: 'Edit', value: 'edit' },
{ text: 'Duplicate', value: 'duplicate' },
{ divider: true },
{ text: 'Delete', value: 'delete', class: 'text-danger' }
],
onSelect: (item) => console.log('Selected:', item)
});
</script>
Tutorial
Build a user profile dropdown with event handling.
Select an option from the dropdown
const dropdown = Domma.elements.dropdown('#user-dropdown', {
items: [
{ header: 'Signed in as user@example.com' },
{ divider: true },
{ text: 'Profile', value: 'profile' },
{ text: 'Settings', value: 'settings' },
{ text: 'Billing', value: 'billing' },
{ divider: true },
{ text: 'Sign Out', value: 'logout' }
],
onOpen: () => console.log('Dropdown opened'),
onClose: () => console.log('Dropdown closed'),
onSelect: (item) => {
console.log(`Action selected: ${item.value}`);
}
});
Examples
Hover Trigger
Positioning
With Dividers and Headers
Programmatic Control
Best Practices
Accessibility
- Keyboard Navigation - Use arrow keys to navigate items, Enter to select, Escape to close
- ARIA Attributes - Add
aria-haspopup="true"andaria-expandedto toggle button - Focus Management - Focus moves to first item when opened
- Screen Readers - Use semantic
elements for triggers
UX Guidelines
- Clear Trigger - Make dropdown button visually distinct with chevron icon
- Logical Grouping - Use dividers and headers to organise menu items
- Close on Action - Enable
closeOnClickfor action menus - Hover Delay - Add slight delay for hover triggers to prevent accidental opens
Performance
- Event Delegation - Attach single listener to menu instead of individual items
- Destroy When Done - Call
destroy()on dynamic dropdowns
API Reference
| Option | Type | Default | Description |
|---|---|---|---|
items |
Array | [] |
Menu items array. Each item: { text, value, class } or { header } or
{ divider: true } |
trigger |
String | 'click' |
Trigger type: 'click' or 'hover' |
position |
String | 'bottom-start' |
Position: bottom-start, bottom-end, top-start, top-end, left-start, right-start |
closeOnClick |
Boolean | true |
Close when item clicked |
closeOnOutside |
Boolean | true |
Close when clicking outside |
animation |
Boolean | true |
Enable animations |
offset |
Number | 4 |
Offset from toggle (px) |
onOpen |
Function | null |
Open callback |
onClose |
Function | null |
Close callback |
onSelect |
Function | null |
Item selection callback - receives selected item object |
Methods
| Method | Description |
|---|---|
open() |
Open the dropdown |
close() |
Close the dropdown |
toggle() |
Toggle dropdown state |
isOpen() |
Check if dropdown is open |
destroy() |
Remove dropdown and clean up |
CSS Classes
| Class | Description |
|---|---|
.dropdown |
Container element |
.dropdown-toggle |
Trigger button |
.dropdown-menu |
Menu container |
.dropdown-item |
Menu item link |
.dropdown-divider |
Visual separator |
.dropdown-header |
Section header text |
Config Engine
$.setup({
'#user-menu': {
component: 'dropdown',
options: {
trigger: 'click',
position: 'bottom-end',
closeOnClick: true,
onOpen: () => console.log('Menu opened')
}
},
'#hover-menu': {
component: 'dropdown',
options: {
trigger: 'hover',
position: 'bottom-start'
}
}
});