TieredMenu
Menus inside menus.
About
Vertical menu whose rows open flyout submenus, for deep action trees such as export formats or posting periods. A row with items shows a chevron; its flyout opens toward the inline end on hover, click or the forward arrow. On a phone, where no flyout fits, the row drills in: its items fill the menu under a back row.
Usage
Basic
A row with children reads aria-haspopup="menu" and aria-expanded, and hovering it opens its flyout. Each level is its own role="menu", named by the row that opened it. Flyouts paint in the top layer, so a box around the menu cannot clip them; a press outside closes them. variant="card" frames a menu at rest.
Open path
openPath holds the open row index per depth, so [1, 0] opens the second root row and then its first child. Nesting has no fixed depth, and width sets every level in px.
Danger and disabled rows
A danger row takes the danger tokens and still picks normally. A disabled row is inert at every level: the keyboard steps over it and it cannot open its own flyout.
Links
A leaf with href is a real link at any depth: suiPick fires on the click, the path collapses, then the browser follows. A row with children opens them instead, whatever its href says.
Events
Several flyouts can be open at once, so the element reports its path with suiOpenPathChange rather than an open and close pair. Picking a leaf emits suiPick, runs its command and collapses the path.
Keyboard
| Key | Action |
|---|---|
| ArrowDown ArrowUp | Moves within the current level, wrapping, and closes any flyout open below it. Separators, section eyebrows and disabled rows are skipped. |
| Home End | Moves to the first or last enabled row of the current level. |
| ArrowRight | On a row with children, opens its flyout and focuses the first row. Under dir="rtl" the pair swaps, so the arrow that points along the reading direction is always the forward one. |
| Enter Space | On a row with children, opens its flyout and focuses the first row. On a leaf, picks it and collapses every flyout, with focus back on the root row that owned the path; on a leaf with href the browser then follows the link. |
| ArrowLeft | Closes the current flyout and returns focus to its parent row. |
| Escape | Closes the current flyout and returns focus to its parent row. At the root, collapses any open path. |
| Tab | In a flyout, closes every flyout and moves on to the control after the menu. |
| Shift+Tab | In a flyout, closes every flyout and returns focus to the root row that opened them. |
| Any letter | Moves to the next row in the current level whose label starts with that letter. |
API
<sui-tiered-menu>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
items | property only | SuiMenuItem[] | [] | Nested rows: { label, icon?, danger?, disabled?, separator?, href?, target?, items?: [...] }[]. A leaf with href is a real link: Enter follows it and suiPick still fires. A row with items opens them instead, whatever its href says. Property, not attribute. |
openPath | property only | number[] | [] | Open row index per depth: [3] opens the fourth root row's flyout, [1, 0] opens two levels. Mutable: the element writes it on every hover, open, collapse and pick and reports each change through suiOpenPathChange. Open flyouts paint in the browser's top layer, so a transformed, contained or clipping ancestor cannot move them or cut them off. A press outside the menu and its flyouts, and Tab from a flyout, collapse the path. Property, not attribute. |
variant | variant | "card" | "plain" | 'plain' | Surface the root level paints. plain is the default: rows only, for a menu inside a sui-popover with flush or any other card. card adds a resting border and rounded corners, no shadow, for a menu that stands on a page by itself. Flyouts always paint their own floating card. Anything else falls back to plain. |
width | width | number | 230 | Width of every flyout in px, and of the root level when it is a card. A plain root takes the width of the box it sits in. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiOpenPathChange | number[] | onSuiOpenPathChange | @sui-open-path-change | Fires whenever the element changes openPath; detail is the new path. Several flyouts can be open at once, so this is indexed expansion as in sui-accordion, not the suiOpen and suiClose pair: the menu is inline, with no trigger and nothing to dismiss. Does not bubble. |
suiPick | SuiMenuItem | onSuiPick | @sui-pick | Fires when a leaf row is picked; detail is the item. item.command() also runs, then the open path collapses to empty. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves keyboard focus to the menu's one tab stop: the highlighted root row, else the first enabled one (the current level's, while a phone-width menu has drilled in). |
Types
SuiMenuItem interface | |||
|---|---|---|---|
label? | string | ||
icon? | string | ||
shortcut? | string | ||
badge? | string | number | ||
danger? | boolean | ||
disabled? | boolean | ||
separator? | boolean | ||
section? | string | Section heading row (uppercase eyebrow). | |
items? | SuiMenuItem[] | Nested items (TieredMenu, Menubar dropdowns). | |
command? | () => void | ||
href? | string | Renders the row as a real link, so middle-click, copy link and open in a new tab work and Enter follows it. The row keeps its styling, its place in the arrow-key order and its pick: command runs and suiPick fires on the click, then the browser navigates. Ignored on a disabled row and on a row with nested items; those stay buttons. | |
target? | string | Link target for a row with href, e.g. _blank. A _blank row gets rel="noopener". | |
current? | boolean | The row is the page the reader is on: it carries aria-current="page" and the bold face sui-side-nav gives its current item. For a navigation menu, the site pages behind a phone menu button; an action menu has no current row. | |
checked? | boolean | Makes the row one choice of a set, for a mode or an order picked from a menu: the chosen row draws a check and every row keeps room for one, and the rows read as menuitemradio with aria-checked. Leave it unset on an action row. | |
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color17
Typography1
Spacing and size1
Radius1
Elevation2
Motion3
Every name above is listed with its value and its role in Foundations.