Skip to content

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.

HTML tag<l-dropdown>
Native HTML
Progressive
Custom
Shadow DOM
Custom Element · Shadow DOM

Options

Basic

Click the trigger to open the menu. Click outside or press Escape to close.

Edit Duplicate Archive
Code
html
<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.

Edit Duplicate Archive Delete
Code
html
<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.

Name Email Phone Address
Code
html
<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>

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.

Layout Compact Comfortable Columns Name Email Phone
Code
html
<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>

Placement

Set placement to control position. Default is bottom-start.

Option 1 Option 2 Option 3 Option 1 Option 2 Option 3 Option 1 Option 2 Option 3
Code
html
<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.

This month This quarter This year
Code
html
<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.

Edit Duplicate
Code
html
<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.

jane.cooper@acme.com Super admin
Manage profile Preferences Get help Sign out
v1.2.3 Documentation
Code
html
<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>

Accessibility

Criteria

Role

Panel has role="menu", items have role="menuitem" or role="menuitemcheckbox"

WCAG4.1.2
RGAA7.1
Expanded state

Trigger receives aria-expanded reflecting open state

WCAG4.1.2
Checked state

Checkbox items use aria-checked to communicate toggle state

WCAG4.1.2
Disabled state

Disabled items use aria-disabled, remaining in the DOM for discoverability

WCAG4.1.2
Focus management

Focus moves into menu on open and returns to trigger on close

WCAG2.4.3
RGAA10.7
Motion

Respects prefers-reduced-motion

WCAG2.3.3

Keyboard interactions

Enter
Opens menu and focuses first item; or selects the focused item
Space
Opens menu and focuses first item; or selects the focused item
ArrowDown
Opens menu and focuses first item; or moves focus to the next item (wraps)
ArrowUp
Opens menu and focuses last item; or moves focus to the previous item (wraps)
Home
Moves focus to the first item
End
Moves focus to the last item
Escape
Closes menu and returns focus to the trigger
Tab
Closes menu and moves focus to the next focusable element

API reference

Importing

js
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 trigger so 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()Method
hide()Method
toggle()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. Detail: { 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-item elements). Drop an <l-divider> (or <hr>) between items to render a section separator, or an <l-dropdown-label> to caption a group of items.
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.
valuestringProperty
The value associated with this item.
disabledbooleandefault:falseProperty
Disables the item.
type'normal' | 'checkbox'default:'normal'Property
The type of item: normal or checkbox.
checkedbooleandefault:falseProperty
Whether the checkbox item is checked.
(default)Slot
Label text.
prefixSlot
Leading content (e.g. icon).
suffixSlot
Trailing content.
(default)Slot
Label text.
--colordefault:var(--l-color-text-tertiary)Custom property
Text color.