Horizontal Menu
Top navigation with popover submenus — the persistent site navigation for a screen set.


Reach for it when you need:
- The main navigation bar of a project
Component name: HorizontalMenu · Category: Navigation
In the palette: Top navigation with popover submenus
Properties
Any property can be bound to a tag, another component's property, or a query.
| Property | Type | Default | Description |
|---|---|---|---|
menu | array | [{"label":"Dashboard","icon":"LayoutDashboard","path":"/dash… (truncated) | — |
gap | number | 8 | — |
align | enum | left | Where the items sit along the row when the menu is wider than them. Options: left · center · right. |
showExternalIcon | boolean | true | Mark items that leave the app with a small arrow glyph. |
style | style | {} | Custom CSS properties |
Events
Attach event actions to these in the Event Manager.
| Event | Label | Group | Payload |
|---|---|---|---|
click | Click | Mouse | The DOM event. |
dblclick | Double click | Mouse | The DOM event. |
contextmenu | Right click | Mouse | The DOM event. |
mouseenter | Mouse enter | Mouse | The DOM event. |
mouseleave | Mouse leave | Mouse | The DOM event. |
contextmenu fires your configured actions at runtime only — in LiveView and in preview. On the Designer canvas the right-click is captured to open the Event Manager, so testing it there will not run your actions. Test right-click in preview.
Notes
Internal and external items
Each item declares what its path means:
- internal — a route inside the project. It is prefixed with the project slug and navigated in-app with no page reload, so a path that happens to look like a hostname (
reports.2024/summary) still resolves as a route. - external — an address outside the app. A bare host is given
https://so the browser does not resolve it against the current page, it opens in a new tab by default withrel="noopener noreferrer", and a small arrow marks it so an operator knows the click leaves the HMI. - auto (the default) — work it out from the path. Fine for obvious cases; state it explicitly when the path is ambiguous.
Use openIn to override the tab in either direction: auto follows the kind, same keeps the operator on the current screen, new opens a second tab.
Making an item do more than navigate
An item does not have to go anywhere. Leave its path empty, give it a key, and handle Menu item click in the Event Manager. The chain receives the clicked item, so ONE handler on the menu covers every entry — each action guarded by the item it belongs to.
Every action is available (popover, panel, notification, sign in, sign out, set tag, set variable, send message, run script) because this is the same action list every other widget uses.
Worked example: Help opens a popover, Sign out signs out
1. Build the popover content. Create a view — say HelpCard — with whatever the popover should show, and give it a size (300 x 200 is a reasonable card). It needs no routing path: a popover hosts it in place.
2. Key the items. Select the menu and open the menu property. On the Help item set key to help; on the Sign out item set it to logout. Leave both path fields empty — these items run actions rather than navigating. (linkType and openIn disappear once a path is empty, which is the schema telling you the same thing.)
3. Open the handler. Right-click the menu on the canvas, choose Menu item click.
4. Add the popover. Add action → Popover. Set View to HelpCard, Anchor to This widget, and leave Side on Auto so it places itself wherever there is room.
5. Guard it to the Help item. On that action tick Only run this action when…, then:
| Field | Value |
|---|---|
| source | {{item.key}} — use the picker, under Event data |
| operator | is |
| value | help |
Without the guard the popover would open for every item in the menu, because the handler belongs to the whole widget rather than to one entry.
6. Add the second action. Add action → Sign out, guarded the same way with {{item.key}} is logout. Guarded actions are skipped cleanly — a skipped action records no result and raises no error, so the two never interfere.
7. Test in preview. Help opens the popover, Sign out signs out, and every other item navigates exactly as before.
Passing the clicked item into the view
Once the popover view declares params, the action shows a View Param table. Any payload field can go straight in:
| Param | Value |
|---|---|
topic | {{item.key}} |
title | {{item.label}} |
The full payload is {{item.key}}, {{item.label}}, {{item.path}}, {{item.href}}, {{item.external}}, {{item.newTab}}, {{item.level}}, {{item.index}} and {{item.hasSubMenu}}.
Renaming "Sign out" to "Log out" would silently unwire a guard that tested the label. The key is yours and changes only when you change it.
The event fires for submenu entries too, and it fires before any navigation — so an item can both run actions and follow its path.
Parking one item at the far end
Set an item's pin to end and it renders in its own group at the far end of the menu — the bottom of a vertical menu, the right of a horizontal one — while everything else stays together at the start. This is per item, which is the point: Sign in, Sign out and Settings need to sit apart from the navigation, and a whole-menu alignment cannot say that.
Pin as many as you like; their order within the pinned group is still yours. pin applies to top-level items only — a submenu opens as a flyout, so it has no far end of its own.
linkType and openIn only show once an item has a path, and no destination field shows on an item that has children — a group expands, it never navigates. Active colours are hidden on an external item, which can never be the page you are on.
Where the items sit
Set align to left, center or right to park the items along the bar when it is wider than they are.