diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/menu.md b/16/umbraco-cms/customizing/extending-overview/extension-types/menu.md index e305a7b8155..2cb8413faf1 100644 --- a/16/umbraco-cms/customizing/extending-overview/extension-types/menu.md +++ b/16/umbraco-cms/customizing/extending-overview/extension-types/menu.md @@ -1,263 +1,70 @@ -# Menu +--- +description: >- + Create menus that appear throughout the backoffice, including in sidebars and button flyouts. +--- -{% hint style="warning" %} -This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice. -{% endhint %} +# Menus + +Menu extensions contain one or more [menu item extensions](menu-item.md) and can appear throughout the backoffice, such as in sidebars and flyouts.

Menu

## Creating a custom menu -In this section, you can learn how to register and create a custom Menu for the Umbraco backoffice. - -### Manifest - -The manifest file can be created using either JSON or TypeScript. Both methods are shown below. +Menu extensions can be created using either JSON or TypeScript. Both approaches are shown below. {% tabs %} - {% tab title="JSON" %} - -We can create the manifest using JSON in the `umbraco-package.json`. - +{% code title="umbraco-package.json" %} ```json { - "type": "menu", - "alias": "My.Menu", - "name": "My Menu" + "$schema": "../../umbraco-package-schema.json", + "name": "My Package", + "version": "0.1.0", + "extensions": [ + { + "type": "menu", + "alias": "My.Menu", + "name": "My Menu" + } + ] } ``` +{% endcode %} {% endtab %} - {% tab title="TypeScript" %} +Extension authors define the menu manifest, then register it dynamically/during runtime using a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point.md) extension. -The manifest can also be written in TypeScript. - -For this TypeScript example we used a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point.md) extension to register the manifests. - +{% code title="my-menu/manifests.ts" %} ```typescript import type { ManifestMenu } from '@umbraco-cms/backoffice/menu'; -const menuManifest: Array = [ - { - type: 'menu', - alias: 'My.Menu', - name: 'My Menu' - } -]; -``` - -{% endtab %} - -{% endtabs %} - -# Menu Item - -

Menu Item

- -Menu items are the items that appear in the menu. - -## Creating a custom menu items - -In this section, you can learn how to add custom Menu Items to your Umbraco backoffice Menu. - -### Manifest - -To add custom menu items, you can define a single MenuItem manifest and link an element to it. In this element, you can fetch the data and render as many menu items as you want based on that data. - -The code snippets below show how to declare a new menu item using JSON or TypeScript. - -{% tabs %} - -{% tab title="JSON" %} - -We can create the manifest using JSON in the `umbraco-package.json`. - -```json -{ - "type": "menuItem", - "alias": "My.MenuItem", - "name": "My Menu Item", - "element": "./menu-items.ts", - "meta": { - "label": "My Menu Item", - "menus": ["My.Menu"] - } -} -``` - -{% endtab %} - -{% tab title="TypeScript" %} - -The manifest can also be written in TypeScript. - -For this TypeScript example we used a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point.md) extension to register the manifests. - -{% code title="manifest.ts" overflow="wrap" lineNumbers="true" %} -```typescript -const menuItemManifest: Array = [ - { - type: 'menuItem', - alias: 'My.MenuItem', - name: 'My Menu Item', - meta: { - label: 'My Menu Item', - menus: ["My.Menu"] - }, - element: () => import('./menu-items.ts') - } -]; +export const menuManifest: ManifestMenu = { + type: 'menu', + alias: 'My.Menu', + name: 'My Menu' +}; ``` {% endcode %} - -{% endtab %} - -{% endtabs %} - -### The UI Element - -#### Rendering menu items with Umbraco's UI menu item component - -To render your menu items in Umbraco, you can use the [Umbraco UI Menu Item component](https://uui.umbraco.com/?path=/docs/uui-menu-item--docs). This component allows you to create nested menu structures with a few lines of code. - -By default, you can set the `has-children` attribute to display the caret icon indicating nested items. It will look like this: `?has-children=${bool}`. - -**Example:** - -```tsx - - - - -``` - -#### Custom menu item element example - -You can fetch the data and render the menu items using the Lit element above. By putting the result of the fetch in a `@state()`, we can trigger a re-render of the component when the data is fetched. - -{% code title="menu-items.ts" overflow="wrap" lineNumbers="true" %} +{% code title="entrypoints/entrypoints.ts" %} ```typescript -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'; - -const elementName = 'my-menu-item'; - -@customElement(elementName) -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 +import type { + UmbEntryPointOnInit, +} from "@umbraco-cms/backoffice/extension-api"; +import { umbExtensionsRegistry } from "@umbraco-cms/backoffice/extension-registry"; +import { menuManifest } from "./../my-menu/manifests.ts"; - 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` - - ${element.type === 1 - ? html`` - : html``} - - ${element.hasChildren ? this.renderItems(element.children) : ''} - - `)} - `; - } - - // Main render function - override render() { - if (this._loading) { - return html``; - } - - if (this._error) { - return html` - `; - } - - // Render items if loading is done and no error occurred - return this.renderItems(this._items); - } -} - -export { MyMenuItems as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: MyMenuItems; - } -} +export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { + console.log("Hello from my extension 🎉"); + umbExtensionsRegistry.register(menuManifest); +}; ``` {% endcode %} +{% endtab %} +{% endtabs %} - -## Tree Menu Item - -### Manifest - -```json -// it will be something like this -{ - "type": "menuItem", - "kind": "tree", - "alias": "My.TreeMenuItem", - "name": "My Tree Menu Item", - "meta": { - "label": "My Tree Menu Item", - "menus": ["My.Menu"] - } -} -``` - -#### Default Element - -The default element supports rendering a subtree of menu items. - -```typescript -class UmbMenuItemTreeDefaultElement {} -``` - -### Adding menu items to an existing menu - -The backoffice comes with a couple of menus. - -* Content, Media, Settings, Templating, Dictionary, etc. - -To add a menu item to an existing menu, you can use the `meta.menus` property. - -```typescript -{ - "type": "menuItem", - "alias": "My.MenuItem", - "name": "My Menu Item", - "meta": { - "label": "My Menu Item", - "menus": ["Umb.Menu.Content"] - } -} -``` +## See Also +* [Section Sidebar](sections/section-sidebar.md) for information on creating menus for navigation within section extensions. +* [Menu Item](menu-item.md) for information on creating menu items.