Dropdown
The dropdown component can be used to show a list of menu items when clicking on an element such as a button and hiding it when focusing outside of the triggering element.
<div style="min-height: 304px">
<twig:Dropdown id="demo" open>
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sign out</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
Installation
Available since UX Toolkit 3.0.
php bin/console ux:install dropdown --kit flowbite-4
Install the following Composer dependencies:
composer require symfony/ux-icons twig/html-extra:^3.24.0 symfony/ux-twig-component:^3.5 tales-from-a-dev/twig-tailwind-extra:^1.3.0
Install the following front-end dependencies:
npm install flowbite
# ...or with Symfony AssetMapper
php bin/console importmap:require flowbite
Copy the following file(s) into your app:
import { Controller } from '@hotwired/stimulus';
import { Dropdown } from 'flowbite';
export default class extends Controller {
dropdown = null;
static targets = ['trigger', 'content'];
static values = {
placement: String,
triggerType: String,
open: Boolean,
delay: Number,
offsetDistance: Number,
};
connect() {
const options = {
placement: this.placementValue,
triggerType: this.triggerTypeValue,
delay: this.delayValue,
offsetDistance: this.offsetDistanceValue,
};
this.dropdown = new Dropdown(this.contentTarget, this.triggerTarget, options);
this.dropdown.updateOnShow(() => {
this.triggerTarget.setAttribute('aria-expanded', 'true');
});
this.dropdown.updateOnHide(() => {
this.triggerTarget.setAttribute('aria-expanded', 'false');
});
this._onTriggerKeydown = this._handleTriggerKeydown.bind(this);
this._onContentKeydown = this._handleContentKeydown.bind(this);
this.triggerTarget.addEventListener('keydown', this._onTriggerKeydown);
this.contentTarget.addEventListener('keydown', this._onContentKeydown);
if (this.openValue) {
this.dropdown.show();
}
}
disconnect() {
this.triggerTarget.removeEventListener('keydown', this._onTriggerKeydown);
this.contentTarget.removeEventListener('keydown', this._onContentKeydown);
this.dropdown?.destroy();
this.dropdown = null;
}
_getMenuItems() {
// Get menuitems belonging to this menu level only (not nested submenu contents).
// Items can be: li > a[role="menuitem"] (Item) or li > div[data-controller] > button[role="menuitem"] (SubTrigger)
const items = [];
for (const item of this.contentTarget.querySelectorAll('[role="menuitem"]')) {
if (item.closest('[data-dropdown-target="content"]') === this.contentTarget) {
items.push(item);
}
}
return items;
}
_focusItem(index) {
const items = this._getMenuItems();
if (items.length === 0) return;
const i = ((index % items.length) + items.length) % items.length;
items[i].focus();
}
_focusFirstItem() {
this._focusItem(0);
}
_focusLastItem() {
this._focusItem(-1);
}
_show(focusFirst = true) {
this.dropdown.show();
if (focusFirst) {
// Small delay to ensure the content is visible before focusing
requestAnimationFrame(() => this._focusFirstItem());
}
}
_hide() {
this.dropdown.hide();
this.triggerTarget.focus();
}
_handleTriggerKeydown(event) {
// If this trigger is a SubTrigger (role="menuitem"), arrow keys should be
// handled by the parent menu for navigation, not by this submenu's trigger.
const isSubTrigger = this.triggerTarget.getAttribute('role') === 'menuitem';
switch (event.key) {
case 'ArrowDown':
if (isSubTrigger) return;
if (!this.dropdown.isVisible()) {
event.preventDefault();
this._show(true);
}
break;
case 'ArrowUp':
if (isSubTrigger) return;
if (!this.dropdown.isVisible()) {
event.preventDefault();
this.dropdown.show();
requestAnimationFrame(() => this._focusLastItem());
}
break;
case 'Enter':
case ' ':
if (!this.dropdown.isVisible()) {
event.preventDefault();
this._show(true);
}
break;
case 'Escape':
if (this.dropdown.isVisible()) {
event.preventDefault();
this._hide();
}
break;
}
}
_handleContentKeydown(event) {
// Only handle if the focused element belongs to this menu level
const items = this._getMenuItems();
const currentIndex = items.indexOf(document.activeElement);
if (currentIndex === -1) return;
// Stop propagation to prevent parent dropdown controllers from intercepting
event.stopPropagation();
switch (event.key) {
case 'ArrowDown':
event.preventDefault();
this._focusItem(currentIndex + 1);
break;
case 'ArrowUp':
event.preventDefault();
this._focusItem(currentIndex - 1);
break;
case 'Home':
event.preventDefault();
this._focusFirstItem();
break;
case 'End':
event.preventDefault();
this._focusLastItem();
break;
case 'Escape':
event.preventDefault();
this._hide();
break;
case 'Tab':
this._hide();
break;
case 'ArrowRight':
// If focused on a SubTrigger, open the submenu
if (document.activeElement.getAttribute('aria-haspopup') === 'menu') {
event.preventDefault();
document.activeElement.click();
// Focus first item in the submenu after it opens
requestAnimationFrame(() => {
const subContent = document.activeElement
?.closest('[data-controller="dropdown"]')
?.querySelector('[data-dropdown-target="content"]');
if (subContent) {
const firstItem = subContent.querySelector('[role="menuitem"]');
if (firstItem) firstItem.focus();
}
});
}
break;
case 'ArrowLeft':
// If inside a submenu, close it and return focus to the SubTrigger
this._closeParentSubmenu(event);
break;
}
}
_closeParentSubmenu(event) {
// Check if this controller is a submenu (nested inside another dropdown)
const parentDropdown = this.element.closest('li[role="none"]')?.closest('[data-controller="dropdown"]');
if (parentDropdown && parentDropdown !== this.element) {
event.preventDefault();
this._hide();
// The _hide() already focuses our trigger, which is the SubTrigger in the parent menu
}
}
}
{%- props
## string Unique identifier for generating internal IDs.
id,
## boolean Whether the dropdown is open on initial render.
open = false,
## 'bottom'|'top'|'left'|'right'|'left-start'|'left-end'|'right-start'|'right-end'|'bottom-start'|'bottom-end'|'top-start'|'top-end' The dropdown placement relative to the trigger.
placement = 'bottom',
## 'click'|'hover' The dropdown trigger type.
triggerType = 'click',
## int The dropdown delay.
delay = 300,
## int The dropdown content offset.
offsetDistance = 10
-%}
{%- set _dropdown_id = 'dropdown-' ~ id -%}
{%- set _dropdown_trigger_id = _dropdown_id ~ '-trigger' -%}
<div
data-dropdown-placement-value="{{ placement }}"
data-dropdown-trigger-type-value="{{ triggerType }}"
data-dropdown-open-value="{{ open ? 'true' : 'false' }}"
data-dropdown-delay-value="{{ delay }}"
data-dropdown-offset-distance-value="{{ offsetDistance }}"
{{ attributes.defaults({
'data-controller': 'dropdown',
}) }}
>
{##- The dropdown structure (Dropdown:Trigger and Dropdown:Content). -#}
{%- block content %}{% endblock -%}
</div>
<div
id="{{ _dropdown_id }}"
data-dropdown-target="content"
role="menu"
aria-labelledby="{{ _dropdown_trigger_id }}"
{{ attributes.defaults({
class: 'z-10 bg-neutral-primary-medium border border-default-medium rounded-base shadow-lg w-fit min-w-44 divide-y divide-default-medium hidden'|tailwind_classes,
}) }}
>
{##- The dropdown menu content, typically includes `Dropdown:Group`, `Dropdown:Header`. -#}
{%- block content %}{% endblock -%}
</div>
<ul
role="group"
{{ attributes.defaults({
class: 'p-2 text-sm text-body font-medium'|tailwind_classes,
}) }}
>
{##- The list of `Dropdown:Item` elements. -#}
{%- block content %}{% endblock -%}
</ul>
<div
role="none"
{{ attributes.defaults({
class: 'm-2 p-2 text-sm text-body bg-neutral-secondary-strong border-0 rounded'|tailwind_classes,
}) }}
>
{##- The header content (e.g., user name, email). -#}
{%- block content %}{% endblock -%}
</div>
{%- props
## string The item tag.
as = 'a'
-%}
{% set _attributes_defaults = {} %}
{% if as == 'button' %}
{% set _attributes_defaults = {type: 'button'} %}
{% endif %}
<li role="none">
<{{ as }}
role="menuitem"
tabindex="-1"
{{ attributes.defaults(_attributes_defaults).defaults({class: 'inline-flex items-center w-full p-2 text-sm font-medium text-body hover:bg-neutral-tertiary-medium hover:text-heading rounded'|tailwind_classes}) }}
>
{##- The item label. -#}
{%- block content %}{% endblock -%}
</{{ as }}>
</li>
{% if __context is defined and __context.id is defined %}
{% set id = null %}
{% endif %}
{%- props
## string Unique identifier for generating internal IDs.
id,
## 'bottom'|'top'|'left'|'right'|'left-start'|'left-end'|'right-start'|'right-end'|'bottom-start'|'bottom-end'|'top-start'|'top-end' The dropdown placement relative to the trigger.
placement = 'right-start',
## 'click'|'hover' The dropdown trigger type.
triggerType = 'click',
## int The dropdown delay.
delay = 300,
## int The dropdown content offset.
offsetDistance = 10
-%}
{%- set _dropdown_id = 'dropdown-sub-' ~ id -%}
{%- set _dropdown_trigger_id = _dropdown_id ~ '-trigger' -%}
{##- The dropdown structure (Dropdown:SubTrigger and Dropdown:Content). -#}
{%- set _dropdown_content = block('content') -%}
<li role="none">
<twig:Dropdown :id="id" :placement="placement" :triggerType="triggerType" :delay="delay" :offsetDistance="offsetDistance" {{ ...attributes }}>
{{- _dropdown_content|raw -}}
</twig:Dropdown>
</li>
{% set _subtrigger_icons = {
right: 'flowbite:chevron-right-outline',
top: 'flowbite:chevron-up-outline',
bottom: 'flowbite:chevron-down-outline',
} %}
{% set _subtrigger_icon = _subtrigger_icons[placement|split('-')|first] ?? null %}
<button
data-dropdown-target="trigger"
id="{{ _dropdown_trigger_id }}"
type="button"
role="menuitem"
tabindex="-1"
aria-expanded="false"
aria-haspopup="menu"
aria-controls="{{ _dropdown_id }}"
{{ attributes.defaults({
class: 'inline-flex items-center w-full p-2 text-sm font-medium text-body hover:bg-neutral-tertiary-medium hover:text-heading rounded'|tailwind_classes,
}) }}
>
{##- The trigger label that toggles the sub dropdown when clicked. -#}
{%- block content %}{% endblock -%}
{% if _subtrigger_icon %}
<twig:ux:icon :name="_subtrigger_icon" class="size-4 ms-auto" aria-hidden="true" />
{% endif %}
</button>
{%- set dropdown_trigger_attrs = {
'data-dropdown-target': 'trigger',
id: _dropdown_trigger_id,
'aria-expanded': 'false',
'aria-controls': _dropdown_id,
} -%}
{##- The trigger element (e.g., a `Button`) that toggles the dropdown when clicked. -#}
{%- block content %}{% endblock -%}
Usage
<twig:Dropdown
id="string"
open="true | false"
placement="right | left | top | bottom | right-start | right-end | left-start | left-end | top-start | top-end | bottom-start | bottom-end"
triggerType="click | hover"
delay="300"
offsetDistance="10"
>
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Header>
<span class="block text-sm text-heading font-medium">Bonnie Green</span>
<span class="block text-sm truncate">name@flowbite.com</span>
</twig:Dropdown:Header>
<twig:Dropdown:Group>
<twig:Dropdown:Item as="a" href="#">Link item</twig:Dropdown:Item>
<twig:Dropdown:Item as="button">Button item</twig:Dropdown:Item>
<twig:Dropdown:Sub
id="string"
placement="right | left | top | bottom | right-start | right-end | left-start | left-end | top-start | top-end | bottom-start | bottom-end"
triggerType="click | hover"
delay="300"
offsetDistance="10"
>
<twig:Dropdown:SubTrigger>
Sub menu
</twig:Dropdown:SubTrigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Sub item</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sub item</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown:Sub>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
Examples
Dropdown hover
Use the ̀triggerType="{hover|click}" prop options to set whether the dropdown should be shown when hovering or clicking on the trigger element (ie. button).
There’s a 300ms default delay when showing or hiding the dropdown due to UI/UX reasons and how it may affect the interaction with other components on the page. Generally, we recommend using the click method.
<div style="min-height: 304px">
<twig:Dropdown id="hover" triggerType="hover">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sign out</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
Delay duration
You can use the delay={milliseconds} prop options to set the delay on when to show or hide the dropdown menu when using hover. You may want to use this depending on how the users interact with your interface.
In this example we add 500 milliseconds instead of the default 300.
<div style="min-height: 304px">
<twig:Dropdown id="delay" triggerType="hover" delay="500">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sign out</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
Dropdown divider
You can use multiple Dropdown:Group, the Dropdown:Content add a divider between the groups.
<div style="min-height: 504px">
<twig:Dropdown id="divider">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sign out</twig:Dropdown:Item>
</twig:Dropdown:Group>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Separated link</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
With header
Use this example to show extra information outside of the list of menu items inside the dropdown.
<div style="min-height: 504px">
<twig:Dropdown id="header">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Header class="flex items-center space-x-1.5">
<twig:Avatar>
<twig:Avatar:Image src="https://flowbite.com/docs/images/people/profile-picture-5.jpg" alt="Bonnie image" />
<twig:Avatar:Fallback>BG</twig:Avatar:Fallback>
</twig:Avatar>
<div class="text-sm">
<div class="font-medium text-heading">Bonnie Green</div>
<div class="truncate text-body">name@flowbite.com</div>
</div>
<twig:Badge border="bordered">PRO</twig:Badge>
</twig:Dropdown:Header>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">
<twig:ux:icon name="flowbite:user-outline" class="size-4 me-2" aria-hidden="true" />
Dashboard
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
<twig:ux:icon name="flowbite:adjustments-horizontal-outline" class="size-4 me-2" aria-hidden="true" />
Settings
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
<twig:ux:icon name="flowbite:lock-outline" class="size-4 me-2" aria-hidden="true" />
Privacy
</twig:Dropdown:Item>
</twig:Dropdown:Group>
<twig:Dropdown:Group>
<twig:Dropdown:Item class="text-fg-danger" href="#">
<twig:ux:icon name="flowbite:arrow-left-to-bracket-outline" class="size-4 me-2" aria-hidden="true" />
Sign out
</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
Multi-level dropdown
Use this example to enable multi-level dropdown menus by adding stacked elements inside of each other.
<div style="min-height: 504px">
<twig:Dropdown id="demo" open>
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown button
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-4" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Sub id="level1">
<twig:Dropdown:SubTrigger>
Settings
</twig:Dropdown:SubTrigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Submenu item</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Submenu item</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown:Sub>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Sign out</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
With icon
Use the menu icon trigger element on components such as cards as an alternative element to the button.
<div style="min-height: 304px">
<div class="flex justify-center space-x-4 rtl:space-x-reverse">
<twig:Dropdown id="icon-vt">
<twig:Dropdown:Trigger>
<twig:Button variant="ghost" size="icon" {{ ...dropdown_trigger_attrs }}>
<twig:ux:icon name="flowbite:dots-vertical-outline" class="size-6" aria-hidden="true"/>
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">
Dashboard
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Settings
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Earnings
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Sign out
</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
<twig:Dropdown id="icon-hz">
<twig:Dropdown:Trigger>
<twig:Button variant="ghost" size="icon" {{ ...dropdown_trigger_attrs }}>
<twig:ux:icon name="flowbite:dots-horizontal-outline" class="size-6" aria-hidden="true"/>
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">
Dashboard
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Settings
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Earnings
</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">
Sign out
</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
</div>
Placement
You can also use the placement={top|right|bottom|left} prop options to choose the placement of the dropdown menu.
By default the positioning is set to the bottom side of the button.
<div class="flex flex-wrap items-center gap-4" style="min-height: 304px">
<twig:Dropdown id="placement-top" placement="top">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown top
<twig:ux:icon name="flowbite:chevron-up-outline" class="size-6" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
<twig:Dropdown id="placement-right" placement="right">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown right
<twig:ux:icon name="flowbite:chevron-right-outline" class="size-6" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
<twig:Dropdown id="placement-bottom" placement="bottom">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
Dropdown bottom
<twig:ux:icon name="flowbite:chevron-down-outline" class="size-6" aria-hidden="true" />
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
<twig:Dropdown id="placement-left" placement="left">
<twig:Dropdown:Trigger>
<twig:Button {{ ...dropdown_trigger_attrs }}>
<twig:ux:icon name="flowbite:chevron-left-outline" class="size-6" aria-hidden="true" />
Dropdown left
</twig:Button>
</twig:Dropdown:Trigger>
<twig:Dropdown:Content>
<twig:Dropdown:Group>
<twig:Dropdown:Item href="#">Dashboard</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Settings</twig:Dropdown:Item>
<twig:Dropdown:Item href="#">Earnings</twig:Dropdown:Item>
</twig:Dropdown:Group>
</twig:Dropdown:Content>
</twig:Dropdown>
</div>
API Reference
<twig:Dropdown>
| Prop | Type | Default |
|---|---|---|
id Unique identifier for generating internal IDs.
|
string |
- |
open Whether the dropdown is open on initial render.
|
boolean |
false |
placement The dropdown placement relative to the trigger.
|
'bottom'|'top'|'left'|'right'|'left-start'|'left-end'|'right-start'|'right-end'|'bottom-start'|'bottom-end'|'top-start'|'top-end' |
'bottom' |
triggerType The dropdown trigger type.
|
'click'|'hover' |
'click' |
delay The dropdown delay.
|
int |
300 |
offsetDistance The dropdown content offset.
|
int |
10 |
| Block | Description |
|---|---|
content |
The dropdown structure (Dropdown:Trigger and Dropdown:Content). |
<twig:Dropdown:Content>
| Block | Description |
|---|---|
content |
The dropdown menu content, typically includes Dropdown:Group, Dropdown:Header. |
<twig:Dropdown:Group>
| Block | Description |
|---|---|
content |
The list of Dropdown:Item elements. |
<twig:Dropdown:Header>
| Block | Description |
|---|---|
content |
The header content (e.g., user name, email). |
<twig:Dropdown:Item>
| Prop | Type | Default |
|---|---|---|
as The item tag.
|
string |
'a' |
| Block | Description |
|---|---|
content |
The item label. |
<twig:Dropdown:Sub>
| Prop | Type | Default |
|---|---|---|
id Unique identifier for generating internal IDs.
|
string |
- |
placement The dropdown placement relative to the trigger.
|
'bottom'|'top'|'left'|'right'|'left-start'|'left-end'|'right-start'|'right-end'|'bottom-start'|'bottom-end'|'top-start'|'top-end' |
'right-start' |
triggerType The dropdown trigger type.
|
'click'|'hover' |
'click' |
delay The dropdown delay.
|
int |
300 |
offsetDistance The dropdown content offset.
|
int |
10 |
| Block | Description |
|---|---|
content |
The dropdown structure (Dropdown:SubTrigger and Dropdown:Content). |
<twig:Dropdown:SubTrigger>
| Block | Description |
|---|---|
content |
The trigger label that toggles the sub dropdown when clicked. |
<twig:Dropdown:Trigger>
| Block | Description |
|---|---|
content |
The trigger element (e.g., a Button) that toggles the dropdown when clicked. |