Dropdown displays a menu with actions or options next to a trigger and supports disabled, loading, footer, and keyboard interaction states.
Add the progress attribute to kbq-dropdown-item to show a loading shimmer on the item. It can be combined with disabled to also prevent interaction while loading.
You can add an extra button inside a menu item (for example, to go to settings). It works independently: clicking it doesn't close the menu, and you can reach it with the Tab key.
The menu item itself should be a regular block, not a button.
If the item is in a loading state, the extra button stays visible but becomes unavailable.
A menu item can be made into a regular link — then the entire block will navigate to another page.
You can place auxiliary elements in the footer: buttons, links, hints.
This mechanism prevents an open nested submenu from closing prematurely while the pointer is moving. The submenu stays open even if the pointer touches sibling items along the way, as long as the movement stays within the designated area. It can be configured in two ways:
safeArea property;KBQ_DROPDOWN_DEFAULT_OPTIONS.A "cyclic navigation" mode where reaching one end of the list loops back to the other end.
Recursive rendering of an array or object, allowing the creation of nested dropdown menus.
The kbqDropdownSearch directive turns a kbq-form-field into the panel's search field: it styles the field for the panel and takes over the keyboard.
The caret stays in the field while the menu is open: ArrowUp and ArrowDown move the highlight across the items, Enter picks the highlighted one, the first Escape clears the query and the second one closes the menu.
Search splits a multi-word query into parts and searches for them independently, trims leading and trailing spaces, is case-insensitive, and folds diacritics. The algorithm is described in the Smart search guide.
kbqDropdownTriggerOrigin detaches the panel from the trigger element: bind an element, or a rectangle in viewport coordinates, and the panel is positioned against that. kbqCreateCaretOrigin from @koobiq/components/core builds such a rectangle out of a measurement it repeats on every reposition — here the / and the query typed after it, which kbqGetTextQuery finds and kbqListenForCaretMoves keeps watching — so the panel keeps up with the caret. updatePosition() moves a panel that is already open, and null anchors it back to the trigger.
Keep the trigger off the editor: it answers Enter and Space itself, so it belongs on a separate element. [kbqDropdownTriggerAutoFocus]="false" leaves the caret in the text, and [activeDescendantNavigation]="true" on the panel makes the arrow keys move the highlight without taking focus — the editor then hands ArrowUp, ArrowDown, Enter and Escape over with handleKeydown($event). The highlighted item is not announced yet: the panel sets no aria-activedescendant.
Use the xPosition property to control horizontal alignment of the dropdown panel relative to the trigger. Supported values: 'after' (default), 'before', and 'center'.
By default the panel grows with its content, is never narrower than its trigger or than 200px, and stops at 640px. This is configured with the same panelWidth, panelMinWidth and panelMaxWidth attributes as select and autocomplete:
<!-- Match the trigger exactly --> <kbq-dropdown panelWidth="auto" /> <!-- An exact width; panelMinWidth is not applied --> <kbq-dropdown [panelWidth]="400" /> <!-- Let the panel grow further with its content --> <kbq-dropdown [panelMaxWidth]="800" />
The 640px cap is soft: it limits growth by content only, so a trigger wider than 640px still gets a panel as wide as itself, and an explicit panelWidth is never clamped.
The defaults come from design tokens, which can be overridden by a theme:
| Token | Default |
|---|---|
--kbq-dropdown-size-container-width-min | 200px |
--kbq-dropdown-size-container-width-max | var(--kbq-panel-size-width-max, 640px) |
--kbq-panel-size-width-max is shared by every dropdown panel in the library, so setting it once on :root caps select, tree-select, autocomplete and dropdown together.
Nested panels and panels that overlap the trigger vertically are not matched to the trigger — they follow the tokens only.
When the trigger is only a part of a larger control, set KbqDropdownTrigger.widthOrigin to the element the panel should match instead. Split button does this through its panelAutoWidth input.
By default, the menu appears above the horizontal Navbar and Topbar. To have a menu opened from the page content slide under them while the page scrolls, mark the content area with kbqOverlayLayer — see Panels under a sticky header. A menu opened from the bar itself, like Actions in the example, stays above it.