import { Component } from '@angular/core';
import { WrDropdown, WrDropdownItem, WrDropdownMenu } from 'ngwr/dropdown';
@Component({ imports: [WrDropdown, WrDropdownItem, WrDropdownMenu] })
export class MyComponent {}Dropdown
A menu that opens from any trigger.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Basic usage
Point [wrDropdown] at a <wr-dropdown-menu>. A click on an item does not close the menu; call close() on the trigger.
<!-- Items do not close the menu: d.close() does. -->
<button wr-btn type="button" [wrDropdown]="menu" #d="wrDropdown">Actions</button>
<wr-dropdown-menu #menu>
<wr-dropdown-item icon="copy-outline" (click)="copy(); d.close()">Copy</wr-dropdown-item>
<wr-dropdown-item icon="download" (click)="download(); d.close()">Download</wr-dropdown-item>
<wr-dropdown-item icon="trash" (click)="remove(); d.close()">Delete</wr-dropdown-item>
</wr-dropdown-menu>Positions
Set position. A menu that does not fit flips to the other side.
<button wr-btn type="button" [wrDropdown]="menu" position="top-start">Top start</button>Arrow
On by default. Set [arrow]="false" on a menu with no padding or with clipped overflow.
<!-- On by default -->
<button wr-btn type="button" [wrDropdown]="menu">With arrow</button>
<button wr-btn type="button" [wrDropdown]="menu" [arrow]="false">Without arrow</button>Hover trigger
Closes when the pointer leaves both the trigger and the menu.
<button wr-btn type="button" [wrDropdown]="menu" trigger="hover">Hover me</button>Disabled item
<wr-dropdown-item icon="cog" disabled>Disabled item</wr-dropdown-item>Template reference
The trigger exports wrDropdown, so the template can open, close or read the menu.
<wr-btn [wrDropdown]="menu" #actions="wrDropdown">Actions</wr-btn>
<wr-dropdown-menu #menu>
<wr-dropdown-item>Copy</wr-dropdown-item>
</wr-dropdown-menu>
<!-- Anywhere else in the same template -->
<wr-btn (click)="actions.toggle()">Toggle from here</wr-btn>
@if (actions.isOpen()) {
<span>The menu is up.</span>
}The trigger keeps its own id
Set your own id for tests: the generated one changes between pages.
<!-- The menu gets aria-labelledby="row-actions" -->
<button wr-btn type="button" id="row-actions" [wrDropdown]="menu">Actions</button>
<!-- Bound ids work too -->
<button wr-btn type="button" [id]="'actions-' + row.id" [wrDropdown]="menu">Actions</button>Scrolling containers
Add cdkScrollable to your own scrolling box, or the menu drifts from its trigger. Every anchored ngwr overlay needs it.
import { CdkScrollable } from '@angular/cdk/scrolling';
@Component({
imports: [CdkScrollable, WrDropdown, WrDropdownMenu, WrDropdownItem],
template: `
<div class="side-panel" cdkScrollable>
<button wr-btn type="button" [wrDropdown]="menu">Actions</button>
</div>
`,
})
export class PanelComponent {}Directive API
| Name | Description | Type | Default |
|---|---|---|---|
wrDropdownrequired | Menu to open. Pass a <wr-dropdown-menu> template reference. | WrDropdownMenu | — |
trigger | How the menu opens. | WrDropdownTrigger | 'click' |
position | Where the menu anchors relative to the trigger. A placement that does not fit flips to the opposite side (a left / right menu may also drop below or above, and then stays there until it closes), and the pane's wr-dropdown-overlay--<placement> class names the side it actually took. | WrDropdownPosition | 'bottom-start' |
arrow | Draw a small arrow on the menu's edge, pointing at the trigger — the one wr-popover and wr-popconfirm draw, from the same shared rule. It follows the placement the menu actually took, so a flipped menu points the right way, and it widens the gap to the trigger from 0.25rem to popover's 0.5rem so the tip does not touch the control. Turn it off on a menu with no padding of its own (--wr-dropdown-padding: 0) or one that clips its overflow: the square reaches about 3px inside the menu's border, over the first row, and overflow cuts its tip off. Read when the menu opens. | boolean | true |
panelClass | Extra CSS classes for the menu's overlay pane. The pane is appended to the overlay container, not to this component, so nothing in the consumer's own template encloses it and no descendant rule written around the trigger can reach it. This input is the only per-instance handle on it. A space-separated string works as well as an array. | WrClassInput | null |
(opened) | Fires after the menu opens. | void | — |
(closed) | Fires after the menu closes. | void | — |
Item API
| Name | Description | Type | Default |
|---|---|---|---|
icon | Optional leading icon name. | WrIconName | null | null |
disabled | Disable interaction (suppresses pointer + keyboard). | boolean | false |
CSS variables
Set these on the component's selector or a wrapper, not on :root: the defaults are declared on ngwr/dropdown's own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-dropdown-bg | var(--wr-color-surface) | .wr-dropdown-menu |
--wr-dropdown-border | var(--wr-border-base) | .wr-dropdown-menu |
--wr-dropdown-font-family | var(--wr-font-family-base) | .wr-dropdown-menu |
--wr-dropdown-item-bg-hover | var(--wr-color-hover) | .wr-dropdown-item |
--wr-dropdown-item-color | var(--wr-color-on-surface) | .wr-dropdown-item |
--wr-dropdown-item-font-size | var(--wr-text-sm) | .wr-dropdown-item |
--wr-dropdown-item-gap | var(--wr-space-sm) | .wr-dropdown-item |
--wr-dropdown-item-line-height | var(--wr-text-sm-leading) | .wr-dropdown-item |
--wr-dropdown-item-padding-x | var(--wr-space-md) | .wr-dropdown-item |
--wr-dropdown-item-padding-y | var(--wr-space-sm) | .wr-dropdown-item |
--wr-dropdown-item-radius | var(--wr-border-radius-sm) | .wr-dropdown-item |
--wr-dropdown-min-width | 10rem | .wr-dropdown-menu |
--wr-dropdown-padding | var(--wr-space-xs) | .wr-dropdown-menu |
--wr-dropdown-radius | var(--wr-border-radius-base) | .wr-dropdown-menu |
--wr-dropdown-shadow | var(--wr-shadow-overlay) | .wr-dropdown-menu |
Dependencies
See also
Component Context MenuA right-click menu for any element.Component PopoverShow a template, or a text tooltip, next to its trigger.Component SelectPick one or several values from a list, with search and free-text tags.Component ButtonA button for an action or a link.Component IconRenders an SVG icon you register by name; ngwr ships none of its own.Guide OverlayStyle ngwr's floating panels and control where focus goes.