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/rootIndentare removed; spacing is handled internally.defaultExpandedKeysandvalue/activeKeycontrol expanded and active state;update:valueis emitted on selection.renderIconhelpers are not built-in; passicon: () => h(IconComponent)directly.
Props (common)
| ghl-ui Prop | HighRise Prop | Notes |
|---|---|---|
value/v-model | value + v-model:value | Active key. |
options | options | Structured items with key/label/children. |
defaultExpandedKeys | default-expanded-keys | Array of keys expanded on load. |
activeKey | value | Use v-model:value for controlled active item. |
| - | collapsed | Collapse/expand menu (if used with sider). |
| - | accordion | Only one subgroup open at a time (optional). |
| - | render-label/render-icon | Use 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
- Keep
keyvalues stable and unique. - Use
default-expanded-keysto open submenus by default; toggleaccordionwhen only one should be open. - Provide icons via
icon: () => h(Icon)per option; avoid global render helpers. - Use
noPaddingfor custom-rendered options (e.g., button rows).