Dropdowns

Dropdown menus that just work. They're built on top of Floating UI and Alpine.js. While they often seem simple on the surface, you might be surprised how complex they are under the hood. Things like focus states, keyboard navigation, accessibility, and positioning are all (usually) handled for you.


Using Dropdowns

To use a dropdown, use the <ui:dropdown> tag with an <x-slot:trigger> to define the triggering element (usually a button).

Here's what an example dropdown might look like:

Basic Dropdown Menu
Copied!
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Click Me, If You Dare...</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>Grizzly Bears</ui:dropdown-item>
6 <ui:dropdown-item>Polar Bears</ui:dropdown-item>
7 <ui:dropdown-item>Panda Bears</ui:dropdown-item>
8 <ui:dropdown-item>Teddy Bears</ui:dropdown-item>
9</ui:dropdown>
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Click Me, If You Dare...</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>Grizzly Bears</ui:dropdown-item>
6 <ui:dropdown-item>Polar Bears</ui:dropdown-item>
7 <ui:dropdown-item>Panda Bears</ui:dropdown-item>
8 <ui:dropdown-item>Teddy Bears</ui:dropdown-item>
9</ui:dropdown>

Properties

Property Type Default Description
offset integer 4 The pixel-value gap between the menu and the trigger element.
See the Alpine docs on offset for more.
position string bottom The dropdown's location relative to the trigger element.
See the Alpine docs on positioning for possible values.

Offset

The the gap between the dropdown and the triggering element as a pixel value. This value is passed directly to Alpine's Anchor plugin, which is built on top of Floating UI. Most of the time you'll want the default value, but if you need more or less space you can use this property to achieve it.

1<ui:dropdown offset="10">
2 ...
3</ui:dropdown>
1<ui:dropdown offset="10">
2 ...
3</ui:dropdown>
Copied!

Position

The dropdown's location relative to the trigger element. This value is passed directly to Alpine's Anchor plugin too. The default value is bottom, but you can also use top, top-start, top-end, left, left-start, left-end, bottom-start, bottom-end, right, right-start, and right-end.

1<ui:dropdown position="top">
2 I open above the trigger element.
3</ui:dropdown>
1<ui:dropdown position="top">
2 I open above the trigger element.
3</ui:dropdown>
Copied!

Slots

Trigger

Use <x-slot:trigger> to define the trigger element.

The Trigger Slot
1<x-slot:trigger>
2 <button>...</button>
3</x-slot:trigger>
1<x-slot:trigger>
2 <button>...</button>
3</x-slot:trigger>
Copied!

Dropdown Items

Use the <ui:dropdown-item> component to define menu items. The default slot is the item's main label. Note that content gets wrapped in a <span> tag to allow for automatic spacing within menu items.

Dropdown Item
1<ui:dropdown-item>
2 Make it grrreat!
3</ui:dropdown-item>
1<ui:dropdown-item>
2 Make it grrreat!
3</ui:dropdown-item>
Copied!

Properties

Dropdown items have a few properties:

Property Type Default Description
dismiss boolean true Close the outer dropdown menu when the item is clicked (or focused and enter is pressed)
focusOnHover boolean true Focus the item when hovered over. Use kebab-case like :focus-on-hover="false"
spacing string space-x-2 A Tailwind CSS Spacing Utility class, like space-x-2.
icon string null Include an Icon before the dropdown item's main content.
iconAfter string null Include an Icon after the dropdown item's main content.
iconVariant string micro The icon variant to use. micro (default), mini, solid, or outline

Icons

The icon property is used to include an icon before the dropdown item's main content.

1<ui:dropdown-item icon="arrow-down">...</ui:dropdown-item>
1<ui:dropdown-item icon="arrow-down">...</ui:dropdown-item>
Copied!
Menu Items - Icons
Copied!
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Dropdown Items with Icons</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item icon="arrow-down">Icons</ui:dropdown-item>
6 <ui:dropdown-item icon="arrows-pointing-in">Provided by</ui:dropdown-item>
7 <ui:dropdown-item icon="bell-alert">Heroicons</ui:dropdown-item>
8</ui:dropdown>
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Dropdown Items with Icons</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item icon="arrow-down">Icons</ui:dropdown-item>
6 <ui:dropdown-item icon="arrows-pointing-in">Provided by</ui:dropdown-item>
7 <ui:dropdown-item icon="bell-alert">Heroicons</ui:dropdown-item>
8</ui:dropdown>

Icon Position

The icon-after property is used to include an icon after the dropdown item's main content.

1<ui:dropdown-item icon-after="arrow-down">...</ui:dropdown-item>
1<ui:dropdown-item icon-after="arrow-down">...</ui:dropdown-item>
Copied!
Menu Items - Icons After
Copied!
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Dropdown Items with Icons After</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item icon-after="arrow-down">Icons</ui:dropdown-item>
6 <ui:dropdown-item icon-after="arrows-pointing-in">Provided by</ui:dropdown-item>
7 <ui:dropdown-item icon-after="bell-alert">Heroicons</ui:dropdown-item>
8</ui:dropdown>
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Dropdown Items with Icons After</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item icon-after="arrow-down">Icons</ui:dropdown-item>
6 <ui:dropdown-item icon-after="arrows-pointing-in">Provided by</ui:dropdown-item>
7 <ui:dropdown-item icon-after="bell-alert">Heroicons</ui:dropdown-item>
8</ui:dropdown>

Slots

The <ui:dropdown-item> has two named slots: before and after. Use the before slot to add content before the menu item's main content -- or the after slot to add content after it. These slots are most commonly used for icons or to denote further actions (such as a hover menu).

1<ui:dropdown-item>
2 <x-slot:before>...</x-slot:before>
3 ...
4 <x-slot:after>...</x-slot:after>
5</ui:dropdown-item>
1<ui:dropdown-item>
2 <x-slot:before>...</x-slot:before>
3 ...
4 <x-slot:after>...</x-slot:after>
5</ui:dropdown-item>
Copied!
Menu Items - Before / After Slots
Copied!
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Example Before / After Slots</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>
6 <x-slot:before>
7 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
8 <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z" />
9 </svg>
10 </x-slot:before>
11 Menu Item with Before / After icons
12 <x-slot:after>
13 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
14 <path fill-rule="evenodd" d="M15.28 9.47a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 1 1-1.06-1.06L13.69 10 9.97 6.28a.75.75 0 0 1 1.06-1.06l4.25 4.25ZM6.03 5.22l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L8.69 10 4.97 6.28a.75.75 0 0 1 1.06-1.06Z" clip-rule="evenodd" />
15 </svg>
16 </x-slot:after>
17 </ui:dropdown-item>
18</ui:dropdown>
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Example Before / After Slots</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>
6 <x-slot:before>
7 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
8 <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z" />
9 </svg>
10 </x-slot:before>
11 Menu Item with Before / After icons
12 <x-slot:after>
13 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
14 <path fill-rule="evenodd" d="M15.28 9.47a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 1 1-1.06-1.06L13.69 10 9.97 6.28a.75.75 0 0 1 1.06-1.06l4.25 4.25ZM6.03 5.22l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L8.69 10 4.97 6.28a.75.75 0 0 1 1.06-1.06Z" clip-rule="evenodd" />
15 </svg>
16 </x-slot:after>
17 </ui:dropdown-item>
18</ui:dropdown>

Slot Attribute Forwarding

The before and after slots are also wrapped in a <span> tag, and the slot attributes are forwarded to it by default. This means you can use the class attribute to style the content within each slot.

1<ui:dropdown-item>
2 <x-slot:before class="text-red-500">...</x-slot:before>
3 ...
4 <x-slot:after class="text-blue-500">...</x-slot:after>
5</ui:dropdown-item>
1<ui:dropdown-item>
2 <x-slot:before class="text-red-500">...</x-slot:before>
3 ...
4 <x-slot:after class="text-blue-500">...</x-slot:after>
5</ui:dropdown-item>
Copied!
Menu Items - Before / After Slots with Classes
Copied!
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Example Before / After Slots with Classes</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>
6 <x-slot:before class="text-red-500">
7 RED
8 </x-slot:before>
9 Menu Item with Before / After icons
10 <x-slot:after class="text-blue-500">
11 BLUE
12 </x-slot:after>
13 </ui:dropdown-item>
14</ui:dropdown>
1<ui:dropdown>
2 <x-slot:trigger>
3 <ui:button>Example Before / After Slots with Classes</ui:button>
4 </x-slot:trigger>
5 <ui:dropdown-item>
6 <x-slot:before class="text-red-500">
7 RED
8 </x-slot:before>
9 Menu Item with Before / After icons
10 <x-slot:after class="text-blue-500">
11 BLUE
12 </x-slot:after>
13 </ui:dropdown-item>
14</ui:dropdown>
Like this project? Stop by the bear cave to stargaze.