Skip to content

Migrating from UIMenu to HighRise Menu

HLMenu is a HighRise-styled menu with enhanced option structure and icon handling. IDs are optional.

Component Implementation Changes

Import Changes

diff
- import { UIMenu } from '@gohighlevel/ghl-ui'
+ import { HLMenu } from '@platform-ui/highrise'

Breaking Changes / Differences

  • Option structure encourages key, label, icon, children, type (group | divider).
  • indent / rootIndent are removed; spacing is handled internally.
  • defaultExpandedKeys and value/activeKey control expanded and active state; update:value is emitted on selection.
  • renderIcon helpers are not built-in; pass icon: () => h(IconComponent) directly.

Props (common)

ghl-ui PropHighRise PropNotes
value/v-modelvalue + v-model:valueActive key.
optionsoptionsStructured items with key/label/children.
defaultExpandedKeysdefault-expanded-keysArray of keys expanded on load.
activeKeyvalueUse v-model:value for controlled active item.
-collapsedCollapse/expand menu (if used with sider).
-accordionOnly one subgroup open at a time (optional).
-render-label/render-iconUse functions on options instead (inline render fns).

Option Shape

typescript
interface MenuOption {
  label: string | (() => VNode)
  key: string | number
  icon?: () => VNode
  disabled?: boolean
  children?: MenuOption[]
  type?: 'group' | 'divider'
  noPadding?: boolean
}

Examples

Basic Menu

vue
<HLMenu :options="menuOptions" v-model:value="activeKey" />

<script setup>
import { h, ref } from 'vue'
import { HomeIcon } from '@gohighlevel/ghl-icons/24/outline'

const activeKey = ref('home')
const menuOptions = [
  { label: 'Home', key: 'home', icon: () => h(HomeIcon) },
  { label: 'Settings', key: 'settings' },
]
</script>

Grouped Menu with Default Expansion

vue
<HLMenu :options="menuOptions" v-model:value="activeKey" :default-expanded-keys="['group-1']" />

<script setup>
import { h, ref } from 'vue'
import { UserIcon } from '@gohighlevel/ghl-icons/24/outline'

const activeKey = ref('item-1')
const menuOptions = [
  {
    type: 'group',
    label: 'Group 1',
    key: 'group-1',
    children: [{ label: 'Item 1', key: 'item-1', icon: () => h(UserIcon) }],
  },
]
</script>

Custom Rendered Item

vue
<HLMenu :options="menuOptions" v-model:value="activeKey" />

<script setup>
import { h, ref } from 'vue'
import { HLButton } from '@platform-ui/highrise'
import { PlaceholderIcon } from '@gohighlevel/ghl-icons/24/outline'

const activeKey = ref('button')
const menuOptions = [
  {
    key: 'button',
    noPadding: true,
    label: () =>
      h(
        HLButton,
        { id: 'new-conversation', size: '3xs', color: 'blue', variant: 'tertiary', style: { width: '100%' } },
        { iconLeft: PlaceholderIcon, default: () => 'New Conversation' }
      ),
  },
]
</script>

Best Practices

  1. Keep key values stable and unique.
  2. Use default-expanded-keys to open submenus by default; toggle accordion when only one should be open.
  3. Provide icons via icon: () => h(Icon) per option; avoid global render helpers.
  4. Use noPadding for custom-rendered options (e.g., button rows).