Dropdown <l-dropdown>
Dropdowns are used to present a list of actions or options in a floating menu anchored to a trigger button. Commonly used for overflow menus, contextual actions, and navigation.
<l-dropdown>Options
Basic
Click the trigger to open the menu. Click outside or press Escape to close.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
Options
</button>
<l-dropdown-item value="edit">Edit</l-dropdown-item>
<l-dropdown-item value="duplicate">Duplicate</l-dropdown-item>
<l-dropdown-item value="archive">Archive</l-dropdown-item>
</l-dropdown>Disabled items
Add disabled to individual items to prevent selection.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
Actions
</button>
<l-dropdown-item value="edit">Edit</l-dropdown-item>
<l-dropdown-item value="duplicate">Duplicate</l-dropdown-item>
<l-dropdown-item disabled>Archive</l-dropdown-item>
<l-dropdown-item value="delete">Delete</l-dropdown-item>
</l-dropdown>Checkbox items
Set type="checkbox" for toggleable items. The dropdown stays open when checking items.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
View columns
</button>
<l-dropdown-item
type="checkbox"
checked
>Name</l-dropdown-item
>
<l-dropdown-item
type="checkbox"
checked
>Email</l-dropdown-item
>
<l-dropdown-item type="checkbox">Phone</l-dropdown-item>
<l-dropdown-item type="checkbox">Address</l-dropdown-item>
</l-dropdown>Destructive items
Set variant="destructive" to mark a delete-style action in red.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
Project
</button>
<l-dropdown-item value="share">
<iconify-icon
slot="prefix"
icon="lucide:share"
></iconify-icon>
Share
</l-dropdown-item>
<l-dropdown-item value="preferences">
<iconify-icon
slot="prefix"
icon="lucide:settings"
></iconify-icon>
Preferences
</l-dropdown-item>
<l-divider></l-divider>
<l-dropdown-label>Danger zone</l-dropdown-label>
<l-dropdown-item value="archive">
<iconify-icon
slot="prefix"
icon="lucide:archive"
></iconify-icon>
Archive
</l-dropdown-item>
<l-dropdown-item
value="delete"
variant="destructive"
>
<iconify-icon
slot="prefix"
icon="lucide:trash-2"
></iconify-icon>
Delete
</l-dropdown-item>
</l-dropdown>Section labels
Add <l-dropdown-label> to caption a group of items. It is non-interactive — keyboard navigation and typeahead skip it. Use <l-divider> between sections.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
View options
</button>
<l-dropdown-label>Layout</l-dropdown-label>
<l-dropdown-item
type="checkbox"
checked
>Compact</l-dropdown-item
>
<l-dropdown-item type="checkbox">Comfortable</l-dropdown-item>
<l-divider></l-divider>
<l-dropdown-label>Columns</l-dropdown-label>
<l-dropdown-item
type="checkbox"
checked
>Name</l-dropdown-item
>
<l-dropdown-item
type="checkbox"
checked
>Email</l-dropdown-item
>
<l-dropdown-item type="checkbox">Phone</l-dropdown-item>
</l-dropdown>Submenus
Nest <l-dropdown-item slot="submenu"> elements inside an item to create a submenu — at any depth. A parent item shows a chevron, opens on hover, click, Enter or ArrowRight, and closes with ArrowLeft or Escape. Selecting a nested item fires the same select event on the dropdown and closes the whole menu (checkbox items keep it open). Use <hr slot="submenu"> for separators inside a submenu.
Code
<l-dropdown>
<button
slot="trigger"
class="l-button"
>
Export
</button>
<l-dropdown-item>
Documents
<l-dropdown-item
slot="submenu"
value="pdf"
>PDF</l-dropdown-item
>
<l-dropdown-item
slot="submenu"
value="docx"
>Word Document</l-dropdown-item
>
</l-dropdown-item>
<l-dropdown-item>
Spreadsheets
<l-dropdown-item slot="submenu">
Excel Formats
<l-dropdown-item
slot="submenu"
value="xlsx"
>Excel (.xlsx)</l-dropdown-item
>
<l-dropdown-item
slot="submenu"
value="csv"
>CSV (.csv)</l-dropdown-item
>
</l-dropdown-item>
<l-dropdown-item
slot="submenu"
value="ods"
>OpenDocument (.ods)</l-dropdown-item
>
</l-dropdown-item>
<hr />
<l-dropdown-item>
Options
<l-dropdown-item
slot="submenu"
type="checkbox"
value="compress"
>Compress files</l-dropdown-item
>
<l-dropdown-item
slot="submenu"
type="checkbox"
checked
value="metadata"
>Include metadata</l-dropdown-item
>
</l-dropdown-item>
</l-dropdown>Placement
Set placement to control position. Default is bottom-start.
Code
<div class="flex gap-4">
<l-dropdown placement="bottom-start">
<button
slot="trigger"
class="l-button"
>
Bottom start
</button>
<l-dropdown-item>Option 1</l-dropdown-item>
<l-dropdown-item>Option 2</l-dropdown-item>
<l-dropdown-item>Option 3</l-dropdown-item>
</l-dropdown>
<l-dropdown placement="bottom-end">
<button
slot="trigger"
class="l-button"
>
Bottom end
</button>
<l-dropdown-item>Option 1</l-dropdown-item>
<l-dropdown-item>Option 2</l-dropdown-item>
<l-dropdown-item>Option 3</l-dropdown-item>
</l-dropdown>
<l-dropdown placement="top-start">
<button
slot="trigger"
class="l-button"
>
Top start
</button>
<l-dropdown-item>Option 1</l-dropdown-item>
<l-dropdown-item>Option 2</l-dropdown-item>
<l-dropdown-item>Option 3</l-dropdown-item>
</l-dropdown>
</div>Min width
Set min-width="trigger" to floor the panel at the trigger's width — useful for select-like triggers (a date-range or filter button). The panel still grows with its content and stays matched if the trigger resizes while open.
Code
<l-dropdown min-width="trigger">
<button
slot="trigger"
class="l-button"
>
1 Jan 2026 – 2 Jun 2026
<l-icon name="lucide:chevron-down"></l-icon>
</button>
<l-dropdown-item value="month">This month</l-dropdown-item>
<l-dropdown-item value="quarter">This quarter</l-dropdown-item>
<l-dropdown-item value="year">This year</l-dropdown-item>
</l-dropdown>Disabled
Add disabled to prevent opening.
Code
<l-dropdown disabled>
<button
slot="trigger"
class="l-button"
disabled
>
Options
</button>
<l-dropdown-item value="edit">Edit</l-dropdown-item>
<l-dropdown-item value="duplicate">Duplicate</l-dropdown-item>
</l-dropdown>Examples
Account menu
Use the header slot for a profile row, the prefix slot on each <l-dropdown-item> for a leading icon, and <l-divider> between groups for section breaks — <l-dropdown> tightens slotted <l-divider> spacing automatically.
Code
<l-dropdown>
<l-avatar
slot="trigger"
interactive
name="Jane Cooper"
aria-label="Account"
style="--appearance: circle; --color: var(--color-purple-200)"
></l-avatar>
<div
slot="header"
class="flex items-center gap-3 px-2 py-2"
>
<l-avatar
name="Jane Cooper"
style="--appearance: circle; --color: var(--color-purple-200)"
></l-avatar>
<div class="flex flex-col">
<span class="text-sm font-medium text-primary">jane.cooper@acme.com</span>
<span class="text-xs text-secondary">Super admin</span>
</div>
</div>
<l-divider></l-divider>
<l-dropdown-item value="profile">
<iconify-icon
slot="prefix"
icon="lucide:user-round-cog"
></iconify-icon>
Manage profile
</l-dropdown-item>
<l-dropdown-item value="preferences">
<iconify-icon
slot="prefix"
icon="lucide:settings"
></iconify-icon>
Preferences
</l-dropdown-item>
<l-dropdown-item value="help">
<iconify-icon
slot="prefix"
icon="lucide:life-buoy"
></iconify-icon>
Get help
</l-dropdown-item>
<l-divider></l-divider>
<l-dropdown-item value="signout">
<iconify-icon
slot="prefix"
icon="lucide:log-out"
></iconify-icon>
Sign out
</l-dropdown-item>
<l-divider></l-divider>
<div
slot="footer"
class="flex items-center justify-between gap-2 px-2 py-1.5 text-xs text-secondary"
>
<span>v1.2.3</span>
<a
class="hover:underline"
href="#"
>Documentation</a
>
</div>
</l-dropdown>Theme row
A display setting belongs in the menu as a type="checkbox" item, not as a switch nested inside one. The whole row is then the control — one click target, role="menuitemcheckbox", and the menu stays open so the change is visible immediately. A nested switch would give the row two competing targets, and role="menu" may only own menuitem, menuitemcheckbox and menuitemradio children.
A checkbox item puts its check in the leading column, which leaves no room for an icon. Set check-placement="end" to move the check to the trailing edge and free that column, so the row keeps its icon and shows whether it is on — and its icon lines up with every other row in the menu.
<l-color-scheme-icon> in the prefix slot then morphs from sun to moon as the row toggles. It stays decorative: the row carries the name, the role and the state.
Code
<l-dropdown>
<l-avatar
slot="trigger"
interactive
name="Jane Cooper"
aria-label="Account"
style="--appearance: circle; --color: var(--color-purple-200)"
></l-avatar>
<l-dropdown-item value="whats-new">
<iconify-icon
slot="prefix"
icon="lucide:megaphone"
></iconify-icon>
What's new
</l-dropdown-item>
<l-dropdown-item
type="checkbox"
check-placement="end"
value="theme"
>
<l-color-scheme-icon slot="prefix"></l-color-scheme-icon>
Dark theme
</l-dropdown-item>
<l-divider></l-divider>
<l-dropdown-item value="signout">
<iconify-icon
slot="prefix"
icon="lucide:log-out"
></iconify-icon>
Sign out
</l-dropdown-item>
</l-dropdown>The row reflects and changes the page's color scheme; the same glyph works in a header button, outside any menu.
Accessibility
Criteria
- Role
Trigger is a menu button (
aria-haspopup="menu"); panel hasrole="menu", items haverole="menuitem"orrole="menuitemcheckbox"WCAG4.1.2RGAA7.1- Accessible name
Each
role="menu"panel is named — the root menu after its trigger, every submenu after its parent itemWCAG4.1.2RGAA7.1- Expanded state
Trigger receives
aria-expandedreflecting open stateWCAG4.1.2- Checked state
Checkbox items use
aria-checkedto communicate toggle stateWCAG4.1.2- Submenu state
Items with a submenu expose
aria-haspopup="menu",aria-controls, and reflectaria-expandedWCAG4.1.2- Disabled state
Disabled items use
aria-disabled, remaining in the DOM for discoverabilityWCAG4.1.2- Focus management
Focus moves into menu on open and returns to trigger on close; Tab closes the menu
WCAG2.4.3RGAA10.7- Motion
Respects
prefers-reduced-motionWCAG2.3.3
Keyboard interactions
API reference
Importing
import 'luxen-ui/dropdown';
import 'luxen-ui/dropdown-item';
import 'luxen-ui/dropdown-label';Attributes & Properties
openbooleandefault:falseProperty- Whether the dropdown is open.
placementPlacementdefault:'bottom-start'Property- Preferred placement of the panel.
distancenumberdefault:4Property- Distance in pixels from the trigger.
disabledbooleandefault:falseProperty- Disables the dropdown trigger.
min-width'trigger' | undefinedProperty- Floor the panel's width at the trigger's width. Set to
triggerso the panel is never narrower than the trigger; it still grows with its content. Useful for select-like triggers (a date-range or filter button) where the panel should line up with the control. Re-applies if the trigger resizes while open.
Methods
show()Methodhide()Methodtoggle()Method
Events
showcancelableEvent- Fired before the dropdown opens. Cancelable.
after-showEvent- Fired after the open animation completes.
hidecancelableEvent- Fired before the dropdown closes. Cancelable.
after-hideEvent- Fired after the close animation completes.
selectEvent- Fired when an item is selected, including items nested in submenus. Bubbles. Properties:
item: DropdownItem.
Slots
triggerSlot- The element that triggers the dropdown.
headerSlot- Optional content rendered above the menu items (e.g. a user profile row). Use an
<l-divider>(or<hr>) after it to separate from items. (default)Slot- Menu content (
l-dropdown-itemelements). Drop an<l-divider>(or<hr>) between items to render a section separator, or an<l-dropdown-label>to caption a group of items. Nest items withslot="submenu"inside an item to create a submenu. footerSlot- Optional content rendered below the menu items (e.g. a version label or shortcut row). Use an
<l-divider>(or<hr>) before it to separate from items.
CSS custom properties
--backgroundCustom property- Panel background color.
--border-radiusdefault:8pxCustom property- Panel border radius.
--paddingdefault:0.25remCustom property- Panel inner padding. Slotted
<l-divider>elements bleed by this amount on each side to span the panel edges. --shadowCustom property- Panel box shadow.
--show-durationdefault:150Custom property- Show animation duration in ms.
--hide-durationdefault:150Custom property- Hide animation duration in ms.
dropdown-item Attributes & Properties
valuestringProperty- The value associated with this item.
disabledbooleandefault:falseProperty- Disables the item.
type'normal' | 'checkbox'default:'normal'Property- The type of item:
normalorcheckbox. variant'destructive' | undefineddefault:undefinedProperty- Visual variant.
destructivemarks a delete-style action in red. checkedbooleandefault:falseProperty- Whether the checkbox item is checked.
submenu-openbooleandefault:falseProperty- Whether this item's submenu is open. Managed by the parent
l-dropdown. check-placement'start' | 'end'default:'start'Property- Which side of a
type="checkbox"item carries the check mark.start(the default) puts it in the leading column, where it takes the place of anyprefix.endmoves it to the trailing edge, freeing that column so the item can show its own icon alongside the state. hasSubmenubooleanProperty- Whether this item has nested
slot="submenu"items.
dropdown-item Slots
(default)Slot- Label text.
prefixSlot- Leading content (e.g. icon). A
type="checkbox"item ignores it unlesscheck-placement="end"frees the leading column. suffixSlot- Trailing content.
submenuSlot- Nested
l-dropdown-itemelements rendered in a submenu panel anchored to this item. Drop an<hr>between them for a separator.
dropdown-label Slots
(default)Slot- Label text.
dropdown-label CSS custom properties
--colordefault:var(--l-color-text-tertiary)Custom property- Text color.