Menu
A simple, responsive navigation menu, styled to match the default tabs theme. Optional icons, horizontal / vertical orientation, and inline or pop-up submenus opened by hover or click. Pop-ups keep themselves on screen: a fly-out that has no room on its side opens on the other one instead, and a branch that flips stays flipped as it goes deeper.
Preview
A working preview of Menu in the Brickclay style. Try it.
Interactive playground
- Dashboard
- Projects
- Settings
orientation
submenuMode
trigger
Markup
<bk-menu [items]="items" [(activeItemId)]="active" orientation="vertical" submenuMode="popup" trigger="hover"> </bk-menu>
Event log
Interact with the menu to see emitted events.
Hover or click trigger="hover" | "click"
Hover fly-outs follow the pointer and close as it leaves, with a short grace period so the gap between an item and its panel can be crossed. Click fly-outs stay put until you click the parent again, pick a leaf, or click outside; once one is open, hovering a sibling still switches panels the way a native menubar does. Inline submenus are always click, so this only applies to submenuMode="popup".
Hover (default)
- Navigation One
- Navigation Two
- Navigation Three
Click
Compact size="compact"
The same menu with the type, padding, icons and indent step stepped down, for sidebars and toolbars where the default is too generous. Everything else behaves identically.
Default
- Navigation Two Option 5 Option 6 Option 7 Option 8
- Navigation Three Option 9 Option 10 Submenu Sub-item 1 Sub-item 2
Compact
Compact, horizontal menubar with pop-ups
- Home
- Products
- Company
- Docs
Staying on screen
A fly-out opens to the right by default, and to the left when the right has no room for it, and the other way round, so a branch that flipped left keeps going left instead of doubling back over its own parent. This menu is pinned to the right edge: hover it and the panels come out leftwards. Narrow the window to watch the ones above flip too.
Single-open (accordion) [singleOpen]="true"
Opening one menu collapses the others so the whole menu stays compact, only one submenu is expanded at a time. Try opening "Navigation Two", then "Navigation Three".
Single-open with a getter-sourced [items]
Fixed bug, kept here as a regression demo. [items] below is bound to a getter that returns a brand-new array of brand-new object literals on every read, a common Angular pattern, and this page forces extra change-detection passes every 300ms so that getter keeps re-running while you look at it (tick: 5). bk-menu used to treat every such reference change as a reason to re-collapse every singleOpen branch, so opening "Navigation Two" here would immediately re-close itself. Try it, it now stays open.
Active item auto-expands its ancestors
Setting activeItemId to a nested leaf expands every submenu on its path, on the very first change, not only when the user clicks to open a branch. This is what makes a sidebar built on bk-menu land with the right section already open after a deep link or a page refresh, with no extra code in the page using it (inline mode only, pop-up fly-outs stay driven by hover/click). This menu starts with activeItemId = 'sub1', two levels deep, reload this page and "Navigation Three > Submenu" is already open below.
Many items, vertical scroll [maxHeight]="'300px'"
With maxHeight set, the menu scrolls vertically once it has too many items. In pop-up mode the fly-outs are positioned fixed, so they render outside the scrolling nav instead of being clipped.
Inline, scrolls at 300px
- Section 1 SECTION 1 Section 1 · Item A Section 1 · Item B Section 1 · Item C
- Section 2 SECTION 2 Section 2 · Item A Section 2 · Item B Section 2 · Item C
- Section 3 SECTION 3 Section 3 · Item A Section 3 · Item B Section 3 · Item C
- Section 4 SECTION 4 Section 4 · Item A Section 4 · Item B Section 4 · Item C
- Section 5 SECTION 5 Section 5 · Item A Section 5 · Item B Section 5 · Item C
- Section 6 SECTION 6 Section 6 · Item A Section 6 · Item B Section 6 · Item C
- Section 7 SECTION 7 Section 7 · Item A Section 7 · Item B Section 7 · Item C
- Section 8 SECTION 8 Section 8 · Item A Section 8 · Item B Section 8 · Item C
- Section 9 SECTION 9 Section 9 · Item A Section 9 · Item B Section 9 · Item C
- Section 10 SECTION 10 Section 10 · Item A Section 10 · Item B Section 10 · Item C
- Section 11 SECTION 11 Section 11 · Item A Section 11 · Item B Section 11 · Item C
- Section 12 SECTION 12 Section 12 · Item A Section 12 · Item B Section 12 · Item C
Pop-up, scrolls at 300px (fly-outs escape)
- Section 1
- Section 2
- Section 3
- Section 4
- Section 5
- Section 6
- Section 7
- Section 8
- Section 9
- Section 10
- Section 11
- Section 12
Basic usage
// component.ts items: MenuItem[] = [ { id: 'home', label: 'Home', icon: 'assets/home.svg' }, { id: 'products', label: 'Products', childrenLabel: 'Our products', // titles the child group children: [ { id: 'p1', label: 'Overview' }, { id: 'p2', label: 'Pricing' }, ], }, ]; active = 'home'; // template <bk-menu [items]="items" [(activeItemId)]="active" orientation="vertical" submenuMode="popup" trigger="hover" size="default" (itemClick)="onSelect($event)"> </bk-menu>
API reference
Component inputs / outputs <bk-menu>
| Name | Type | Default | Possible values | Description |
|---|---|---|---|---|
items | MenuItem[] | [] | array of items | The menu tree. See MenuItem below. |
orientation | MenuOrientation | 'vertical' | 'vertical' | 'horizontal' | Stacked column vs. a horizontal menubar row. |
submenuMode | MenuSubmenuMode | 'inline' | 'inline' | 'popup' | Submenus expand in place (accordion) or open as adaptive pop-ups. |
trigger | MenuTrigger | 'hover' | 'hover' | 'click' | How pop-ups open. Ignored by inline submenus, which are always click. |
size | MenuSize | 'default' | 'default' | 'compact' | Compact shrinks type, padding, icons and the inline indent step. |
singleOpen | boolean | false | true | false | Keep one submenu open per level, opening a parent collapses its siblings. (Pop-up mode always does this.) |
activeItemId | string | '' | any leaf id | Selected leaf id. Two-way bindable via [(activeItemId)]. In inline mode, setting it (including the first binding) auto-expands every ancestor on its path, see Active item auto-expands ancestors. |
maxHeight | string | number | null | '300px', 60, … | Caps the menu height and scrolls vertically past it. Pop-up fly-outs are fixed, so they still escape the scroll box. |
tintIcons | boolean | true | true | false | Force item icons to monochrome (near-black, white on the active row). Turn off to keep original icon colours. |
activeItemIdChange | EventEmitter<string> | – | output | Emits the new active id (drives two-way binding). |
itemClick | EventEmitter<MenuItem> | – | output | Emits the clicked leaf item. |
Menu item MenuItem
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier, matched against activeItemId. |
label | string | Yes | Visible menu text. |
icon | string | No | Icon URL. Tinted monochrome unless tintIcons is false. |
iconAlt | string | No | Alt text; defaults to label. |
disabled | boolean | No | Disables the item and blocks opening its submenu. |
childrenLabel | string | No | Heading titling this item's child group, rendered the same inline or in a pop-up. Ignored without children. |
children | MenuItem[] | No | Nested items. Presence makes the item expandable (chevron shown). |
groupLabel | string | No | Splits this item's siblings into named sections, a heading over each run of siblings sharing the same value, with a rule between sections. For one heading over a whole children array, use childrenLabel instead. |