Skip to content

Migrating from ghl-ui Dropdown to HighRise Dropdown

This guide will help you migrate from the ghl-ui Dropdown component to the HighRise Dropdown component.

Component Implementation Changes

Import Changes

diff
- import { UIDropdown } from '@gohighlevel/ghl-ui'
+ import { HLDropdown } from '@platform-ui/highrise'

Basic Usage Changes

diff
- <UIDropdown :options="options">
-   <UIButton>Click me</UIButton>
- </UIDropdown>
+ <HLDropdown id="my-dropdown" :options="options" trigger="click" placement="bottom-start">
+   <HLButton>Click me</HLButton>
+ </HLDropdown>

Props Changes

Core Props

ghl-ui PropHighRise PropNotes
-idOptional; auto-generated when omitted.
optionsoptionsUses HLDropdownOption[] (see format below).
triggertrigger'click' (default), 'hover', 'focus'.
placementplacementDefaults to bottom-start; RTL-aware remapping.
-showArrowControls arrow visibility (default true).
-widthNumber in px or 'auto' (default 182).
-showSelectedMarkShow checkmark for selected items (default false).
-treeModeEnables hierarchical navigation (default false).
-showSearchAdds built-in search row (default true).
-multipleMulti-select support (default false).
-closeOnSelectClose after select (default true).
-searchValueUse with v-model:searchValue for controlled search input.
-onSearchCustom search handler; skips built-in filtering when provided.
-maxHeightConstrain menu height (px string).
-clearableInSearchShow clear button in search input (default false).

Options Format

typescript
interface HLDropdownOption {
  key: string | number
  label: string
  type?: 'default' | 'divider' | 'header' | 'search' | 'label'
  children?: HLDropdownOption[]
  selected?: boolean
  href?: string
  target?: string
  description?: string
  descriptionIcon?: string
  infoText?: string
  prefix?: boolean
  prefixHandler?: () => void
  hidePrefix?: boolean
  titleRightSlot?: () => VNode
  searchPlaceholder?: string
  onChange?: (value: string) => void
  disabled?: boolean
}

Examples

Basic Dropdown

vue
<template>
  <HLDropdown
    id="basic-dropdown"
    :show-search="false"
    :options="[
      { key: '1', label: 'Option 1' },
      { key: '2', label: 'Option 2' },
      { key: '3', label: 'Option 3' },
    ]"
  >
    <HLButton>Open Menu</HLButton>
  </HLDropdown>
</template>
vue
<template>
  <HLDropdown
    id="folderMenu"
    :options="[...contextMenuItems, { key: '4', label: 'Option 4', type: 'label', titleRightSlot: () => h('div', 'Option 4') }]"
    placement="bottom"
    @select="onChangeOption"
  >
    <HLButton>Click to open dropdown</HLButton>
  </HLDropdown>
</template>

With Search and Selected Items

vue
<template>
  <HLDropdown id="searchable-dropdown" :options="options" show-selected-mark :width="250" :show-search="true">
    <HLButton>Select Items</HLButton>
  </HLDropdown>
</template>

<script setup>
const options = [
  { key: '1', label: 'Option 1', selected: true },
  { key: '2', label: 'Option 2' },
  { key: '3', label: 'Option 3', description: 'Additional information', descriptionIcon: 'InfoIcon' },
]
</script>

Tree Mode

vue
<template>
  <HLDropdown id="tree-dropdown" :options="treeOptions" tree-mode :show-search="false">
    <HLButton>Navigate</HLButton>
  </HLDropdown>
</template>

<script setup>
const treeOptions = [
  {
    key: '1',
    label: 'Category 1',
    children: [
      { key: '1-1', label: 'Subcategory 1.1' },
      { key: '1-2', label: 'Subcategory 1.2' },
    ],
  },
  {
    key: '2',
    label: 'Category 2',
    children: [
      { key: '2-1', label: 'Subcategory 2.1' },
      { key: '2-2', label: 'Subcategory 2.2' },
    ],
  },
]
</script>

Best Practices

  1. Provide stable IDs when testing or targeting specific triggers.
  2. Use showSearch for large option sets; pair with onSearch for remote filtering.
  3. Enable treeMode for hierarchical data; consider closeOnSelect=false for multi-level navigation.
  4. Set width to auto when you need the menu to match the trigger width.
  5. Use showSelectedMark with multiple to surface selection state in the menu.