Layout
Menubar A horizontal menu bar with multiple dropdown menus, following the ARIA menubar pattern.
npm pnpm yarn bun
npm install @morphos/layout
import {
Menubar,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarItem,
MenubarSeparator,
} from '@morphos/layout'
@ Component ()
class MyComponent extends StatefulComponent {
@ State () menubar = new Menubar ({ 'aria-label' : 'Application menu' })
@ State () fileMenu = new MenubarMenu ({ menubar: this .menubar, value: 'file' })
@ State () editMenu = new MenubarMenu ({ menubar: this .menubar, value: 'edit' })
render () {
return (
< Menubar menubar = { this .menubar}>
< MenubarMenu menubar = { this .menubar} value = "file" >
< MenubarTrigger menu = { this .fileMenu}>File</ MenubarTrigger >
< MenubarContent menu = { this .fileMenu}>
< MenubarItem menu = { this .fileMenu} value = "new" label = "New" onSelect = {() => console. log ( 'new' )} />
< MenubarItem menu = { this .fileMenu} value = "open" label = "Open…" onSelect = {() => console. log ( 'open' )} />
< MenubarSeparator />
< MenubarItem menu = { this .fileMenu} value = "save" label = "Save" onSelect = {() => console. log ( 'save' )} />
</ MenubarContent >
</ MenubarMenu >
< MenubarMenu menubar = { this .menubar} value = "edit" >
< MenubarTrigger menu = { this .editMenu}>Edit</ MenubarTrigger >
< MenubarContent menu = { this .editMenu}>
< MenubarItem menu = { this .editMenu} value = "undo" label = "Undo" onSelect = {() => console. log ( 'undo' )} />
< MenubarItem menu = { this .editMenu} value = "redo" label = "Redo" onSelect = {() => console. log ( 'redo' )} />
</ MenubarContent >
</ MenubarMenu >
</ Menubar >
)
}
}
MenubarContent renders its dropdown through a Portal (from @praxisjs/runtime), positioned with @morphos/core's computeAnchorPosition against the trigger's bounding rect.
Component Description MenubarRoot — tracks which menu is active (role="menubar") MenubarMenuOne dropdown in the bar — bridges Menubar and its parts, computes the dropdown's anchored position MenubarTriggerButton that opens/closes a menu (role="menuitem") MenubarContentThe dropdown panel, rendered in a Portal and anchored to the trigger MenubarItemA selectable item inside the dropdown (role="menuitem") MenubarSeparatorVisual divider (role="separator")
Prop Type Default Description aria-labelstring— Accessible label for the menubar classstring— CSS class on the root <div role="menubar"> idstring— id on the root element
Method Description open(id: string)Opens the menu with the given value, closing any other open menu close()Closes the currently open menu toggle(id: string)Opens the given menu if closed, or closes it if it's the currently open one
Prop Type Default Description menubarMenubar— The shared Menubar root instance valuestring— Unique identifier for this menu side"top" | "bottom" | "left" | "right""bottom"Which edge of the trigger the menu is placed against align"start" | "center" | "end""start"Alignment of the menu along the trigger's perpendicular axis sideOffsetnumber4Gap in pixels between the trigger and the menu classstring— CSS class idstring— HTML id
Prop Type Default Description menuMenubarMenu— The parent MenubarMenu instance childrenChildren— Button label classstring— CSS class idstring— HTML id (defaults to the menu's generated trigger id)
Prop Type Default Description menuMenubarMenu— The parent MenubarMenu instance childrenChildren— MenubarItem/MenubarSeparator elementsclassstring— CSS class applied to the rendered <ul> idstring— HTML id (defaults to the menu's generated content id)
Prop Type Default Description menuMenubarMenu— The parent MenubarMenu instance valuestring— Item identifier labelstring— Display text, rendered when no children are provided onSelect() => void— Called when the item is selected (before the menu closes) disabledboolean— Disables the item and blocks selection classstring— CSS class idstring— HTML id
Prop Type Default Description classstring— CSS class idstring— HTML id
Interaction Action Click a trigger Toggle its menu open/closed; opening one menu closes any other Click outside the trigger and content Close the active menu EscapeClose the active menu
Arrow-key navigation between menu items or between adjacent triggers is not implemented — MenubarContent only listens for Escape and outside clicks/mousedown on document while its menu is open.
Attribute Element When present data-disabledMenubarItem The item's disabled prop is set
Each MenubarMenu receives both the shared Menubar instance (via the menubar prop) and is itself passed as the menu prop to its MenubarTrigger/MenubarContent/MenubarItem children. MenubarContent's position is recomputed from MenubarTrigger's bounding rect every time the menu opens, using the side/align/sideOffset props on MenubarMenu.
.morphos-menubar-trigger:hover ,
.morphos-menubar-trigger [ aria-expanded = "true" ] {
background : var ( --morphos-color-bg-hover );
}
.morphos-menubar-content {
/* Portaled to document.body, so it can't inherit the page's font. */
font-family : var ( --morphos-font );
z-index : 100 ;
}
.morphos-menubar-item [ data-disabled ] {
opacity : 0.5 ;
cursor : not-allowed ;
}