Skip to content

Accessibility: Work in progress

Translations: Not Needed

Select

Select component for choosing single or multiple options

Default Select


Please Select
Vue
html
<template>
  <HLSelect :options="simpleSelectOptions" :value="selectedValue" @update:value="handleSimpleChange" />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const simpleSelectOptions = [
    {
      label: 'Option 1',
      value: 'option1',
    },
    {
      label: 'Option 2',
      value: 'option2',
    },
    {
      label: 'Option 3',
      value: 'option3',
    },
  ]

  const handleSimpleChange = value => {
    selectedValue.value = value
  }
</script>

With Icon


Please Select
html
<template>
  <HLSelect type="avatar" :options="options" :value="selectedValue" @update:value="handleChange">
    <template #icon>
      <div class="hr-select-menu-placeholder-icon">
        <User01Icon />
      </div>
    </template>
  </HLSelect>
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { User01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Searchable Select


Please Select
html
<template>
  <HLSelect filterable showSearchIcon :options="options" :value="selectedValue" @update:value="handleChange" />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Multiple Selection


Please Select
html
<template>
  <HLSelect
    multiple
    type="avatar"
    filterable
    showSearchIcon
    :options="options"
    :value="selectedValue"
    :showAvatarInTags="false"
    @update:value="handleChange"
    id="select-multiple"
  />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Multiple Selection without Avatar


Please Select
html
<template>
  <HLSelect
    multiple
    filterable
    showSearchIcon
    :options="simpleMultiSelectOptions"
    :value="selectedValue"
    @update:value="handleSimpleMultiChange"
    id="select-multiple"
    :showAvatarInTags="false"
  />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleSimpleMultiChange = value => {
    selectedValue.value = value
  }
</script>
ts
const simpleMultiSelectOptions = [
  {
    label: 'Option 1 with a long label to test the overflow',
    value: 'option1',
  },
  {
    label: 'Option 2 with a long label to test the overflow',
    value: 'option2',
  },
  {
    label: 'Option 3 with a long label to test the overflow',
    value: 'option3',
  },
  {
    label: 'Option 4',
    value: 'option4',
  },
  {
    label: 'Option 5',
    value: 'option5',
  },
  {
    label: 'Option 6',
    value: 'option6',
  },
]

Use remote search when you need to fetch options dynamically from an API or when dealing with large datasets that should be filtered server-side.


html
<template>
  <HLSelect
    id="remote-search"
    :value="selectedValue"
    :options="filteredOptions"
    :loading="loading"
    :filterable="true"
    :remote="true"
    placeholder="Type to search..."
    aria-label="Remote search select example"
    @search="handleSearch"
    @update:value="handleChange"
  />
</template>

<script setup>
  import { ref } from 'vue'
  import { HLSelect } from '@platform-ui/highrise'

  const selectedValue = ref(null)
  const loading = ref(false)
  const filteredOptions = ref([])

  const handleSearch = async query => {
    loading.value = true

    try {
      // Simulate API delay
      await new Promise(resolve => setTimeout(resolve, 1000))

      // Filter results if there's a query, otherwise show all
      filteredOptions.value =
        query && query.trim()
          ? InfiniteScrollOptions.value.filter(option => option.label.toLowerCase().includes(query.toLowerCase().trim()))
          : InfiniteScrollOptions.value
    } catch (error) {
      console.error('Search failed:', error)
      filteredOptions.value = []
    } finally {
      loading.value = false
    }
  }

  // Load initial options
  handleSearch('')

  const handleChange = (value, option) => {
    selectedValue.value = value
    console.log('Selected:', { value, option })
  }
</script>

Infinite Scroll


Please Select
Vue
html
<template>
  <HLSelect
    :options="InfiniteScrollOptions"
    :value="infiniteSelectedValue"
    @update:value="handleInfiniteChange"
    @scroll="handleScroll"
    :reset-menu-on-options-change="false"
    :loading="infiniteLoading"
  />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const infiniteSelectedValue = ref(null)
  const infiniteLoading = ref(false)
  const infiniteSelectedValue = ref(null)
  const handleInfiniteChange = value => {
    infiniteSelectedValue.value = value
  }
  const handleScroll = async event => {
    const scrollPosition = event.target.scrollTop + event.target.clientHeight
    if (scrollPosition >= event.target.scrollHeight - 10) {
      infiniteLoading.value = true
      const result = await fetchOptions() // fetch API
      InfiniteScrollOptions.value = [...InfiniteScrollOptions.value, ...result]
      infiniteLoading.value = false
    }
  }
  const InfiniteScrollOptions = ref([
    {
      label: 'Option 1',
      value: 'option1',
    },
    {
      label: 'Option 2',
      value: 'option2',
    },
  ])
</script>

Inline Select Variants

Default Inline


Please Select
html
<template>
  <HLSelect :options="options" :value="selectedValue" @update:value="handleChange" :inline="true" size="sm" />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Inline with CTA


Please Select
html
<HLSelect
  :options="options"
  :value="selectedValue"
  @update:value="handleChange"
  :inline="true"
  :showInlineCTA="showInlineCTA"
  :show="show"
  :filterable="true"
  size="sm"
  @handleConfirm="handleConfirm"
  @handleCancel="handleCancel"
  @update:show="handleUpdateShow"
/>
ts
const show = ref(false)
const showInlineCTA = ref(false)

const handleConfirm = () => {
  show.value = false
  showInlineCTA.value = false // Hide CTA only on confirm
}

const handleCancel = () => {
  selectedValue.value = null
  show.value = false
  showInlineCTA.value = false // Hide CTA only on cancel
}
const handleUpdateShow = value => {
  show.value = value
  showInlineCTA.value = true
}

Inline with Bottom Border


Please Select
html
<template>
  <HLSelect
    :options="options"
    :value="selectedValue"
    @update:value="handleChange"
    :inline="true"
    :showInlineBottomBorder="true"
    size="sm"
  />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Rounded Tags


Please Select
html
<template>
  <HLSelect
    :options="options"
    :value="selectedValue"
    @update:value="handleChange"
    :inline="true"
    :multiple="true"
    type="avatar"
    :filterable="true"
    :showSearchIcon="true"
    :roundedTags="true"
    size="sm"
  />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Disabled Inline Select


Please Select
Vue
html
<template>
  <HLSelect :options="options" :value="selectedValue" @update:value="handleChange" :inline="true" :disabled="true" size="sm" />
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
  const options = [
    {
      label: 'Option 1',
      value: 'option1',
    },
  ]
</script>

Error State


Please Select
html
<template>
  <HLFormItem validation-status="error" feedback="This field is required">
    <HLSelect
      :options="options"
      :value="selectedValue"
      @update:value="handleChange"
      :inline="true"
      :showInlineCTA="showInlineCTA"
      :show="show"
      :filterable="true"
      size="sm"
      @handleConfirm="handleConfirm"
      @handleCancel="handleCancel"
      @update:show="handleUpdateShow"
    />
  </HLFormItem>
</template>
<script setup>
  import { HLSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref('')
  const handleChange = value => {
    selectedValue.value = value
  }
</script>
ts
const options = [
  {
    type: 'group',
    label: 'Rubber Soul',
    key: 'Rubber Soul',
    children: [
      {
        label: 'Drive My Car',
        value: 'song1',
        description: 'Drive My Car.ogg',
        tagColor: 'blue',
      },
      {
        label: 'Norwegian Wood',
        value: 'song2',
        description: 'Norwegian Wood.ogg',
        tagColor: 'green',
      },
      {
        label: "Everybody's Got Something to Hide Except Me and My Monkey",
        value: 'song0',
        description:
          'lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.lorsum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam. Loresum ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nunc. Nulla facilisi. Nullam.',
        tagColor: 'blue',
      },
      // ... other songs
    ],
  },
  {
    type: 'group',
    label: 'Let It Be',
    key: 'Let It Be Album',
    children: [
      {
        label: 'Two Of Us',
        value: 'Two Of Us',
        tagColor: 'purple',
      },
      {
        label: 'Dig A Pony',
        value: 'Dig A Pony',
        description: 'Dig A Pony.avi',
        tagColor: 'orange',
      },
      // ... other songs
    ],
  },
]

Teleport Select

By default, the select dropdown menu is rendered within its parent component's DOM tree. However, this can cause styling and positioning issues, especially when the select is used inside containers with overflow: hidden, fixed positioning, or complex z-index stacking contexts (like modals, dialogs, or fixed sidebars).

The to prop allows you to teleport (move) the dropdown menu to a different location in the DOM tree, outside of its parent component. This ensures the dropdown remains visible and correctly positioned, regardless of its parent container's styling constraints.

You can specify the target location using:

  • A CSS selector (e.g., to="#select-teleport-target")
  • false to disable teleporting
  • true to teleport to the default location (body)

Please Select
Vue
html
<div id="select-teleport-target"></div>
<HLSelect :options="options" :value="selectedValue" @update:value="handleChange" to="#select-teleport-target" id="select-teleport" />

Custom Rendering

The select component provides powerful customization options through renderOption and tagRenderer props. These allow you to customize both how options appear in the dropdown menu and how selected values are displayed as tags.

How Custom Rendering Works

  1. Render Option (renderOption):

    • Customizes how the option appear in the dropdown menu
    • Can return plain text or complex Vue components
    • Has access to the full option object including custom properties
  2. Tag Rendering (tagRenderer):

    • Customizes how selected values appear in the input
    • Used only when an option is selected
    • Particularly useful with multiple selection
  3. Option Properties:

    • label: The display text or component
    • value: The underlying value
    • tagRenderer: Optional custom tag rendering
    • renderOption: Optional custom label rendering
    • description: Additional text shown below the label
    • Custom styling properties (backgroundColor, color, etc.)
  4. Option Renderer:

    • Customizes how a option appear in the dropdown menu
    • Can return plain text or complex Vue components
    • It will have parameter option

Please Select
html
<script setup>
  import { h } from 'vue'
  import { HLSpace, HLIcon, HLAvatar, HLTag, HLText } from '@platform-ui/highrise'
  import { CheckVerified01Icon } from '@gohighlevel/ghl-icons/24/outline'

  const customOptions = [
    {
      type: 'group',
      label: 'Custom Rendering Examples',
      key: 'custom-group',
      children: [
        {
          label: 'Custom Label with Tag',
          value: 'option1',
          tagRenderer: 'Custom Tag',
          backgroundColor: 'var(--green-50)',
          color: 'var(--green-700)',
          renderOption: () =>
            h('div', { class: 'flex items-center gap-2' }, [
              h('div', 'Custom Label'),
              h(HLTag, { size: 'sm', round: true, variant: 'error' }, { default: () => '2% increase' }),
            ]),
        },
        {
          label: 'Verified Option',
          value: 'option2',
          description: 'With icon and description',
          backgroundColor: 'var(--purple-50)',
          color: 'var(--purple-700)',
          renderOption: () =>
            h(
              HLSpace,
              { align: 'center', wrapItem: false },
              {
                default: () => [h(HLIcon, { size: 'sm' }, { default: () => h(CheckVerified01Icon) }), h('span', 'Verified Option')],
              }
            ),
        },
        {
          label: 'USA',
          value: 'option3',
          backgroundColor: 'var(--orange-50)',
          color: 'var(--orange-700)',
          renderOption: () =>
            h(
              HLSpace,
              { align: 'center', wrapItem: false, justify: 'space-between' },
              {
                default: () => [
                  h(
                    HLSpace,
                    { align: 'center', wrapItem: false },
                    {
                      default: () => [
                        h(HLAvatar, {
                          size: 'xs',
                          src: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1920px-Flag_of_the_United_States.svg.png',
                        }),
                        h('span', 'USA'),
                      ],
                    }
                  ),
                  h(HLText, { size: 'xs' }, { default: () => '+1' }),
                ],
              }
            ),
          tagRenderer: () =>
            h(
              HLSpace,
              { align: 'center', wrapItem: false },
              {
                default: () => [
                  h('img', {
                    style: { width: '16px', height: '16px', borderRadius: '50%' },
                    src: 'https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1920px-Flag_of_the_United_States.svg.png',
                  }),
                  h('span', 'USA'),
                ],
              }
            ),
        },
      ],
    },
  ]

  const optionRenderer = option => {
    if (option.renderOption) {
      return option.renderOption()
    }

    return h('span', option.label)
  }
</script>

<template>
  <HLSelect
    :options="customOptions"
    :value="selectedValue"
    @update:value="handleChange"
    :option-renderer="optionRenderer"
    multiple
    filterable
    id="select-custom-render"
  />
</template>

Imports


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

Props


PropTypeDefaultDescription
id *string | undefinedundefinedUnique identifier for the select
disabledboolean | undefinedundefinedDisables the select
filterableboolean | undefinedundefinedEnables search/filter functionality
loadingboolean | undefinedundefinedShows loading state
multiplebooleanfalseEnables multiple selection
maxTagCountnumber | 'responsive''responsive'Maximum number of visible tags
showboolean | undefinedundefinedControls dropdown visibility
size'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs''sm'Size of the select
type'default' | 'avatar''default'Visual style variant
showSearchIconbooleanfalseShows search icon in input
optionsSelectOption[][]Array of options to display
valuestring | string[] | null | undefinedundefinedSelected value(s)
inlinebooleanfalseUse inline styling
showInlineCTAbooleanfalseShow confirm/cancel buttons
showInlineBottomBorderbooleanfalseShow bottom border in inline mode
roundedTagsbooleanfalseUse rounded styling for tags
showAvatarInTagsbooleanfalseShow avatar in multiple selection
optionRenderer(option: SelectOption) => VNodeChild | undefinedundefinedCustom function to render options
optionHeightnumber | undefinedundefinedHeight of each option in pixels
placeholderstring | undefinedundefinedPlaceholder text when no selection
showArrowboolean | undefinedundefinedShow/hide dropdown arrow
showCheckmarkboolean | undefinedundefinedShow/hide option checkmark
tostring | boolean | undefinedundefinedTeleport dropdown to element/disable
remotebooleanfalseEnable remote search mode. When true, the component will emit search events instead of filtering options locally. Required for async data fetching scenarios.
resetMenuOnOptionsChangebooleanfalseControls whether the dropdown menu position resets when options array changes. Set to true for dynamic content scenarios where menu positioning needs to update.

Types

SelectOption

The options prop accepts an array of SelectOption objects.

ts
interface SelectOption {
  description?: string // Optional description text for the option
  label?: string | (() => VNodeChild) // Option label text or render function
  tagColor?: HLTagColor // Color of the tag (when used in tags mode)
  src?: string // Source URL (e.g. for avatar images)
  tagRenderer?: () => VNodeChild // Custom tag render function
  type: HLSelectOptionType // Type of the option ('group' | 'divider')
  value?: string | number // The value of the option
}

Group Option

When type is 'group', the option can include children:

ts
interface SelectGroupOption extends SelectOption {
  type: 'group'
  label: string // Group header text
  key: string // Unique identifier for the group
  children: SelectOption[] // Array of child options
}

Divider Option

When type is 'divider', it renders a horizontal line separator:

ts
interface SelectDividerOption {
  type: 'divider'
}

Examples

js
// Basic option
{
  label: "Option 1",
  value: "opt1",
  description: "Optional description"
}
js
// Group with children
{
  type: "group",
  label: "Group 1",
  key: "group1",
  children: [
    { label: "Child 1", value: "child1" },
    { type: "divider" },
    { label: "Child 2", value: "child2" }
  ]
}
js
// Tag Renderer
{
  label: "Option 1",
  value: "opt1",
  tagRenderer: () => h(HLTag, { color: "blue" }, "Tag Content")
}

Emits

NameParametersDescription
@update:value(value: string, option: SelectOption)Triggered when selection changes
@update:show(value: boolean)Triggered when dropdown visibility changes
@scroll(e: Event)Triggered on dropdown scroll
@search(value: string)Triggered when search input changes
@clear()Triggered when selection is cleared
@focus()Triggered when input is focused
@blur()Triggered when input is blurred

Methods

NameParametersDescription
focusInput()Focuses the input field
blurInput()Blurs the input field
focus()Focuses the select
blur()Blurs the select

Slots

NameParametersDescription
default()The default content slot
icon()Custom icon slot
header()Header content for dropdown
action()Action content for dropdown
arrow()Custom arrow icon
empty()Content when no options exist