Dropdown

The Dropdown component shows a list of links or actions in a menu that opens from a trigger. Use it for account menus, settings, and any place where a row of buttons would take too much room.

About

The menu opens on click or on hover, depending on triggerEvent. Alignment, animation style and animation speed are all props. Each item can be a link, a button, a header or a divider.

Example

To use the Dropdown component in your project, you first need to import it along with the DropdownItem component. Here's how you can set up the Dropdown in your Svelte component.

Here's a simple example of how to implement the Dropdown component. It includes a label and multiple DropdownItem components, which represent the individual links or actions within the dropdown.

Svelte
<script>
  import { Dropdown, DropdownItem } from "theui-svelte";
</script>

<Dropdown label="Dropdown">
  <DropdownItem href="/">Link 1</DropdownItem>
  <DropdownItem href="/">Link 2</DropdownItem>
  <DropdownItem href="/">Link 3</DropdownItem>
</Dropdown>

In this example, the Dropdown is triggered by a label ("Dropdown"), and it contains three items, each with a URL and text.

Alignment

The align prop in the Dropdown component controls the alignment of the dropdown menu relative to its trigger. You can choose between two options:

  • start: Aligns the dropdown to the start (left) of the trigger element.
  • end: Aligns the dropdown to the end (right) of the trigger element. This is the default alignment.
Svelte
<!-- Align dropdown to the start (left) of the trigger -->
<Dropdown align="start"> ... </Dropdown>

<!-- Default alignment (align to the right of the trigger) -->
<Dropdown align="end"> ... </Dropdown>

Custom Dropdown Trigger

The label prop allows you to set a custom label for the dropdown trigger. You can either use a plain text string or define a custom trigger element using the snippet block.

  • label as props: Directly set the trigger label as a prop.
  • label as snippet: Define a custom trigger with any HTML or component structure.

The trigger is named by its own content, so a trigger with visible text needs nothing else. If your trigger is only an icon or an image, give the dropdown an ariaLabel, for example ariaLabel="Account menu", so screen reader users know what it opens.

Svelte
<!-- Dropdown label by prop -->
<Dropdown label="Dropdown text label"> ... </Dropdown>

<!-- Custom dropdown label by Snippet -->
<Dropdown>
  {#snippet label()}
    <span class="...">Dropdown snippet label</span>
  {/snippet}
</Dropdown>

Animation

Based on your design requirements, you can customize the animation type and the speed of the Dropdown using the animation and animationSpeed props.

Animation Type

The animation prop controls how the menu appears when it opens. The default is slide-up.

  • slide-left: The dropdown slides in from the left.
  • slide-up: The default animation, sliding in from the bottom.
  • slide-right: Slides in from the right.
  • slide-down: Slides in from the top.
  • fade: A smooth fade-in animation.
  • zoom-in: The dropdown zooms in from a smaller size.
  • zoom-out: The dropdown zooms out from a larger size.
Svelte
<Dropdown animation="slide-left"> ... </Dropdown>
<Dropdown animation="slide-up"> ... </Dropdown>  <!-- Default -->
<Dropdown animation="slide-right"> ... </Dropdown>
<Dropdown animation="slide-down"> ... </Dropdown>
<Dropdown animation="fade"> ... </Dropdown>
<Dropdown animation="zoom-in"> ... </Dropdown>
<Dropdown animation="zoom-out"> ... </Dropdown>

Animation Speed

The animationSpeed prop controls the speed of the dropdown animation, allowing for smooth transitions at different paces. It accepts the following values none, slower, slow, normal, fast and faster

Svelte
<Dropdown animationSpeed="slower"> ... </Dropdown>
<Dropdown animationSpeed="slow"> ... </Dropdown>
<Dropdown animationSpeed="medium"> ... </Dropdown>
<Dropdown animationSpeed="fast"> ... </Dropdown>
<Dropdown animationSpeed="faster"> ... </Dropdown>
<Dropdown animationSpeed="none"> ... </Dropdown>

Arrow Icon

The trigger shows a chevron that rotates when the dropdown opens. Set arrowIcon=false to hide it, or pass a snippet to replace it with your own icon. The snippet is rendered in place of the chevron, so any rotation or transition is up to you.

Svelte

<!-- Default chevron -->

<Dropdown label="With arrow"> ... </Dropdown>



<!-- No icon -->

<Dropdown label="No arrow" arrowIcon={false}> ... </Dropdown>



<!-- Your own icon -->

<Dropdown label="Custom arrow">

  {#snippet arrowIcon()}

    <span class="ms-1">+</span>

  {/snippet}

  ...

</Dropdown>

Close on Outside Click

An open dropdown closes by itself when you click anywhere outside it, when you choose an item, and when you press Escape. There is no prop to turn this off. Clicking a header, a divider or empty space inside the menu keeps it open.

In hover mode the dropdown also closes shortly after the pointer leaves it, so a small move off the menu does not close it instantly.

Active State

The active prop in the DropdownItem component is used to indicate whether the item is currently active. This prop accepts a boolean value and defaults to false. When set to true, the item will appear highlighted to show it is active.

Svelte
<Dropdown label="Dropdown">
  <DropdownItem href="/">Link</DropdownItem>
  <DropdownItem href="/" active={true}>Active Link</DropdownItem>
  <DropdownItem href="/">Link</DropdownItem>
</Dropdown>

Using the active prop helps visually distinguish the selected or currently active item within the dropdown.

Customization

The Dropdown component provides several props to customize the appearance of the dropdown items and container. These props allow you to apply custom classes for different elements, giving you full control over the styling.

  • containerClasses: Custom classes for the outer dropdown container.
  • dropdownClasses: Customizes the dropdown content area.
  • itemClasses: Sets custom classes for regular dropdown items.
  • activeItemClasses: Applies custom classes to the active dropdown item.
  • dividerClasses: Customizes the appearance of divider items.
  • headerClasses: Adds custom styling to header items within the dropdown.
  • buttonClasses: Styles the trigger itself, for example buttonClasses="w-full" to make it fill its container.
Svelte
<Dropdown
  label="Customized Dropdown"
  containerClasses="border-4 rounded-xl"
  dropdownClasses="shadow-lg bg-green-50"
  itemClasses="text-green-500 hover:bg-green-100"
  activeItemClasses="text-white bg-green-500"
  dividerClasses="border-b-2 border-green-200"
  headerClasses="text-green-600 text-xs"
>
  <DropdownItem href="/">Link 1</DropdownItem>
  <DropdownItem type="header">Section Header</DropdownItem>
  <DropdownItem type="divider" />
  <DropdownItem href="/" active={true}>Link 2</DropdownItem>
</Dropdown>

These props cover the trigger, the menu and the items, so each part can be styled on its own.

Accessibility

The Dropdown component follows WAI-ARIA best practices.

  • The trigger button uses aria-haspopup="menu", aria-expanded, and aria-controls to describe the dropdown behavior. Its name comes from the trigger content; set ariaLabel when the trigger has no visible text.
  • The dropdown list uses role="menu" with each item using appropriate roles:
    • menuitem on the link or button of each item
    • a heading element for group labels
    • separator for dividers
  • On the trigger, ArrowDown opens the menu, ArrowUp and Escape close it, and Enter or Space toggles it. Keys pressed on an item are left to that item, so Enter follows a link, and Escape still closes the menu and moves focus back to the trigger.

Configuration