Menu Item

Create menu items that appear throughout the backoffice, in sidebars, button flyouts, and more.

Menu Item extensions are used together with Menu extensions. Menu items can be added to custom menus, sidebars, and even the built-in Umbraco menus. Developers can either use the default Menu Item component or create custom Menu Item elements and register them as extensions.

Menu Item

Creating Menu Items

Menu Item extensions can be defined either with JSON in umbraco-package.json or with JavaScript/TypeScript.

Manifest

To add custom menu items, define a single menuItem manifest and link an element to it. Inside that element, you can fetch data and render as many menu items as needed based on that data.

umbraco-package.json
{
    "$schema": "../../umbraco-package-schema.json",
    "name": "My Package",
    "version": "0.1.0",
    "extensions": [
        {
            "type": "menuItem",
            "alias": "My.MenuItem",
            "name": "My Menu Item",
            "element": "./my-menu-item.element.js",
            "meta": {
                "label": "My Menu Item",
                "menus": ["My.Menu"]
            }
        }
    ]
}

Associate Menu Items with Entities

The menuItem extension type accepts an optional entityType property. When set, this property automatically links the menu item to the matching workspace and shows any registered Entity Actions for that entity type.

menu-item.ts
import type { ManifestMenuItem } from '@umbraco-cms/backoffice/menu';

export const menuItemManifest: ManifestMenuItem = {
    type: 'menuItem',
    alias: 'My.MenuItem',
    name: 'My Menu Item',
    meta: {
        label: 'My Menu Item',
        icon: 'icon-wand',
        entityType: 'my-entity-type',
        menus: ["My.Menu"]
    },
};

The Umbraco backoffice streamlines displaying menu items by providing three kinds that extension authors can reuse. These menu item kinds cover common tasks, including registering links, actions, and trees.

Use a link menu item to navigate to another location, typically external URLs.

menu-item.ts
import type { ManifestMenuItem } from '@umbraco-cms/backoffice/menu';

export const menuItemManifest: ManifestMenuItem = {
    type: 'menuItem',
    kind: 'link',
    alias: 'My.MenuItem.ExternalLink',
    name: 'My External Link Menu Item',
    weight: 200,
    meta: {
        label: 'My Link Menu Item',
        icon: 'icon-link',
        href: 'https://',
        menus: ["My.Menu"],
    },
};

Action

Developers can use an action menu item when they want to execute custom logic that runs when the item is clicked. This kind is similar to the default menu item but does not support entityType, and therefore does not automatically link to workspaces or Entity Actions.

menu-item.ts
import type { ManifestMenuItem } from '@umbraco-cms/backoffice/menu';

export const menuItemManifest: ManifestMenuItem = {
    type: 'menuItem',
    kind: 'action',
    alias: 'My.MenuItem.Action',
    name: 'My Action Menu Item',
    api: () => import('./my-action-menu-item.api.js'),
    meta: {
        label: 'My Action Menu Item',
        icon: 'icon-hammer',
        menus: ["My.Menu"],
    },
};
menu-item.api.ts
import { UmbMenuItemActionApiBase } from '@umbraco-cms/backoffice/menu';

export class MyActionMenuItemApi extends UmbMenuItemActionApiBase<never> {
	/**
	 * This method is executed when the menu item is clicked
	 */
	override async execute() {
		console.log('Hello world');
	}
}

// Declare an `api` export so the Extension Registry can initialize this class
export { MyActionMenuItemApi as api };

Tree

Use a tree menu item to show a submenu based on a tree structure. Any existing, registered Tree Repositories can be referenced by its extension alias (treeAlias property) in the Menu Item manifest. This will render a fully functional tree-based menu.

menu-item.ts
import type { ManifestMenuItem } from '@umbraco-cms/backoffice/menu';

export const menuItemManifest: ManifestMenuItem = {
    type: 'menuItem',
    kind: 'tree',
    alias: 'My.MenuItem.Tree',
    name: 'My Tree Menu Item',
    meta: {
        label: 'My Tree Menu Item',
        icon: 'icon-hammer',
        treeAlias: 'My.Repository.Tree',
        menus: ["My.Menu"],
    },
};

Custom Menu Items

Note: You do not need a custom menu item subclass to display menu item extensions. Creating a custom class is optional.

To render custom menu items, developers can use the Umbraco UI Menu Item component. This component supports nested menu structures with minimal markup.

<uui-menu-item> elements accept a has-children boolean attribute, which shows a caret icon to indicate nested items. When using Lit, you can bind this with the ? directive, for example: ?has-children=${boolVariable}.

<uui-menu-item label="Menu Item 1" has-children>
    <uui-menu-item label="Nested Menu Item 1"></uui-menu-item>
    <uui-menu-item label="Nested Menu Item 2"></uui-menu-item>
</uui-menu-item>

Custom menu item element example

Custom elements can fetch data and render menu items using markup like the example above. Storing fetched results in a @state() property ensures the component re-renders whenever the value changes.

menu-items.ts
import type { UmbMenuItemElement } from '@umbraco-cms/backoffice/menu';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, TemplateResult, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { MyMenuItemResponseModel, MyMenuResource } from '../../../api';

@customElement('my-menu-item')
class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
    @state()
    private _items: MyMenuItemResponseModel[] = []; // Store fetched items

    @state()
    private _loading: boolean = true; // Track loading state

    @state()
    private _error: string | null = null; // Track any errors

    override firstUpdated() {
        this.fetchInitialItems(); // Start fetching on component load
    }

    // Fetch initial items
    async fetchInitialItems() {
        try {
            this._loading = true;
            this._items = ((await MyMenuResource.getMenuApiV1()).items); // Fetch root-level items
        } catch (e) {
            this._error = 'Error fetching items';
        } finally {
            this._loading = false;
        }
    }

    // Render items
    renderItems(items: MyMenuItemResponseModel[]): TemplateResult {
        return html`
            ${items.map(element => html`
                <uui-menu-item label="${element.name}" ?has-children=${element.hasChildren}>
                ${element.type === 1
                ? html`<uui-icon slot="icon" name="icon-folder"></uui-icon>`
                : html`<uui-icon slot="icon" name="icon-autofill"></uui-icon>`}
                    <!-- recursively render children -->
                    ${element.hasChildren ? this.renderItems(element.children) : ''}
                </uui-menu-item>
            `)}
        `;
    }

    // Main render function
    override render() {
        if (this._loading) {
            return html`<uui-loader></uui-loader>`;
        }

        if (this._error) {
            return html`<uui-menu-item active disabled label="Could not load form tree!">
        </uui-menu-item>`;
        }

        // Render items if loading is done and no error occurred
        return this.renderItems(this._items);
    }
}

export { MyMenuItems as element };

declare global {
    interface HTMLElementTagNameMap {
        ['my-menu-item']: MyMenuItems;
    }
}

Adding menu items to an existing menu

Developers can add their own menu items to the built-in Umbraco menus.

Examples of built-in menus include:

  • Content - Umb.Menu.Content

  • Media - Umb.Menu.Media

  • Settings - Umb.Menu.StructureSettings

  • Templating - Umb.Menu.Templating

  • And so on.

You can find all available Umbraco menus (nine in total) using the Extension Insights browser by selecting Menu from the dropdown.

Backoffice extension browser

Extending Menus

To add a menu item to an existing menu, use the meta.menus property.

umbraco-package.json
{
    "$schema": "../../umbraco-package-schema.json",
    "name": "My Package",
    "version": "0.1.0",
    "extensions": [
        {
            "type": "menuItem",
            "alias": "My.MenuItem",
            "name": "My Menu Item",
            "meta": {
                "label": "My Menu Item",
                "menus": ["Umb.Menu.Content"]
            },
            "element": "menu-items.js"
        }
    ]
}

Last updated

Was this helpful?