Skip to content
Accessibility: Partial
Translations: Not Needed

Menu

A vertical navigation menu with nested options and icons. Supports unlimited nesting levels with proper indentation and visual hierarchy

Basic Usage

The menu accepts an array of options that define its structure. Each option can use the title property for simple text labels, or label for custom rendered content. Menu items support:

  • Items with icons that can be hidden when expanded (hideIconWhenExpanded)
  • Items with count badges displayed next to the title
  • Nested children with unlimited depth
  • Disabled states
  • Dividers for visual separation
  • Custom rendered items using Vue's h function
Vue
html
<template>
  <HLMenu :options="menuOptions" v-model:value="menuValue" :default-expanded-keys="['inbox', 'assigned']" />
</template>
<script setup lang="ts">
  import { HLMenu } from '@platform-ui/highrise'
  import { renderIcon } from '@platform-ui/highrise/utils'
  import { User01Icon, UserLeft01Icon, UserUp01Icon, Users01Icon, Home01Icon, BezierCurve03Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const menuOptions = [
    {
      key: 'inbox',
      title: 'My Inbox',
      icon: renderIcon(User01Icon),
      hideIconWhenExpanded: true,
      count: '12',
      children: [
        {
          key: 'assigned',
          title: 'Assigned to Me',
          icon: renderIcon(UserLeft01Icon),
          count: '10',
          children: [
            { key: 'unread', title: 'Unread', count: '10' },
            { key: 'all', title: 'All', count: '12' },
            { key: 'recent', title: 'Recent', count: '2' },
            { key: 'starred', title: 'Starred' },
          ],
        },
        { key: 'followed', title: 'Followed by me', icon: renderIcon(UserUp01Icon) },
        { key: 'chat', title: 'Internal Chat', icon: renderIcon(BezierCurve03Icon) },
      ],
    },
    {
      key: 'team-inbox',
      title: 'Team Inbox',
      icon: renderIcon(Users01Icon),
      hideIconWhenExpanded: true,
      count: '3',
      children: [
        { key: 'unread2', title: 'Unread', count: '10' },
        { key: 'all2', title: 'All', count: '12' },
        { key: 'recent2', title: 'Recent', count: '2' },
        { key: 'starred2', title: 'Starred' },
      ],
    },
    { key: 'disabled', title: 'Disabled', icon: renderIcon(User01Icon), disabled: true },
    { key: 'divider-1', type: 'divider' },
    { key: 'manual', title: 'Manual Actions', icon: renderIcon(Home01Icon), hideIconWhenExpanded: true },
  ]

  const menuValue = ref('unread')
</script>

Layout Example

Complete example showing how to use the menu in a typical sidebar layout with header, body, and footer sections.

Content Area

Active menu item: unread

Search value:

Menu collapsed: false

Imports

ts
import { HLMenu } from '@platform-ui/highrise'

Props

NameTypeDefaultDescription
id *string | undefinedundefinedThe id of the element
optionsMenuOption[][]Items data of menu.
valuestring | number | undefinedundefinedSelected Key of the menu item.
defaultExpandedKeysstring[][]The keys of the default expanded menu items.
collapsedbooleanfalseWhether the menu is in collapsed state (icon-only mode).
submenuWidthnumber182Width of the dropdown submenu in collapsed mode (in pixels).
indentnumber16Indentation for nested menu items (in pixels).
rootIndentnumber8Indentation for root level menu items (in pixels).

Types

ts
interface MenuOption {
  key: string | number // Unique identifier
  label?: string | (() => VNode) // Text or custom render function
  title?: string // Convenience field for simple text labels (alternative to label)
  icon?: () => VNode // Optional icon
  count?: string | number // Optional count badge
  hideIconWhenExpanded?: boolean // Hide icon when menu is expanded
  disabled?: boolean // Disable the menu item
  children?: MenuOption[] // Nested menu items
  type?: 'group' | 'divider' // Special item types
}

Emits

NameTypeDescription
update:value(key: string, item: MenuOption)Emitted when the value changes
update:expanded-key(keys: string[])Emitted when the expanded keys change

Methods

NameTypeDescription
deriveResponsiveState() => voidRecalculates the collapsed state of the responsive menu content. Use this method when the menu container's width changes dynamically to ensure proper expansion behavior in responsive mode.
showOption(key: string| number) => voidShow the option