Select
Select component for choosing single or multiple options
Default Select
<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
<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>
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
<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>
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
<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>
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
<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>
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',
},
]
Remote Search
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.
<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
<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
<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>
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
<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"
/>
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
<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>
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
<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>
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
<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
This field is required
<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>
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 teleportingtrue
to teleport to the default location (body
)
<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
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
Tag Rendering (
tagRenderer
):- Customizes how selected values appear in the input
- Used only when an option is selected
- Particularly useful with
multiple
selection
Option Properties:
label
: The display text or componentvalue
: The underlying valuetagRenderer
: Optional custom tag renderingrenderOption
: Optional custom label renderingdescription
: Additional text shown below the label- Custom styling properties (backgroundColor, color, etc.)
Option Renderer:
- Customizes how a option appear in the dropdown menu
- Can return plain text or complex Vue components
- It will have parameter
option
<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
import { HLSelect } from '@platform-ui/highrise'
Props
Prop | Type | Default | Description |
---|---|---|---|
id * | string | undefined | undefined | Unique identifier for the select |
disabled | boolean | undefined | undefined | Disables the select |
filterable | boolean | undefined | undefined | Enables search/filter functionality |
loading | boolean | undefined | undefined | Shows loading state |
multiple | boolean | false | Enables multiple selection |
maxTagCount | number | 'responsive' | 'responsive' | Maximum number of visible tags |
show | boolean | undefined | undefined | Controls dropdown visibility |
size | 'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs' | 'sm' | Size of the select |
type | 'default' | 'avatar' | 'default' | Visual style variant |
showSearchIcon | boolean | false | Shows search icon in input |
options | SelectOption[] | [] | Array of options to display |
value | string | string[] | null | undefined | undefined | Selected value(s) |
inline | boolean | false | Use inline styling |
showInlineCTA | boolean | false | Show confirm/cancel buttons |
showInlineBottomBorder | boolean | false | Show bottom border in inline mode |
roundedTags | boolean | false | Use rounded styling for tags |
showAvatarInTags | boolean | false | Show avatar in multiple selection |
optionRenderer | (option: SelectOption) => VNodeChild | undefined | undefined | Custom function to render options |
optionHeight | number | undefined | undefined | Height of each option in pixels |
placeholder | string | undefined | undefined | Placeholder text when no selection |
showArrow | boolean | undefined | undefined | Show/hide dropdown arrow |
showCheckmark | boolean | undefined | undefined | Show/hide option checkmark |
to | string | boolean | undefined | undefined | Teleport dropdown to element/disable |
remote | boolean | false | Enable remote search mode. When true, the component will emit search events instead of filtering options locally. Required for async data fetching scenarios. |
resetMenuOnOptionsChange | boolean | false | Controls 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.
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:
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:
interface SelectDividerOption {
type: 'divider'
}
Examples
// Basic option
{
label: "Option 1",
value: "opt1",
description: "Optional description"
}
// Group with children
{
type: "group",
label: "Group 1",
key: "group1",
children: [
{ label: "Child 1", value: "child1" },
{ type: "divider" },
{ label: "Child 2", value: "child2" }
]
}
// Tag Renderer
{
label: "Option 1",
value: "opt1",
tagRenderer: () => h(HLTag, { color: "blue" }, "Tag Content")
}
Emits
Name | Parameters | Description |
---|---|---|
@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
Name | Parameters | Description |
---|---|---|
focusInput | () | Focuses the input field |
blurInput | () | Blurs the input field |
focus | () | Focuses the select |
blur | () | Blurs the select |
Slots
Name | Parameters | Description |
---|---|---|
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 |