Usage
Use the v-model directive to control the value of the Listbox or the default-value prop to set the initial value when you do not need to control its state.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
},
{
label: 'Netherlands',
value: 'NL'
},
{
label: 'Poland',
value: 'PL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Portugal',
value: 'PT'
},
{
label: 'Austria',
value: 'AT'
}
])
const value = ref({
label: 'France',
value: 'FR'
})
</script>
<template>
<B24Listbox v-model="value" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
},
{
label: 'Netherlands',
value: 'NL'
},
{
label: 'Poland',
value: 'PL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Portugal',
value: 'PT'
},
{
label: 'Austria',
value: 'AT'
}
])
const value = ref({
label: 'France',
value: 'FR'
})
</script>
<template>
<B24Listbox v-model="value" :items="items" />
</template>
Items
Use the items prop as an array of objects with the following properties:
label?: stringdescription?: stringtype?: "label" | "separator" | "item"icon?: IconComponentavatar?: AvatarPropschip?: ChipPropsdisabled?: booleanonSelect?: (e: Event) => voidclass?: anyb24ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, ... }
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
value: 'ES'
}
])
</script>
<template>
<B24Listbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
value: 'ES'
}
])
</script>
<template>
<B24Listbox :items="items" />
</template>
You can also pass an array of arrays to the items prop to display separated groups of items.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
}
],
[
{
label: 'Brazil',
value: 'BR'
},
{
label: 'Argentina',
value: 'AR'
}
]
])
</script>
<template>
<B24Listbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
}
],
[
{
label: 'Brazil',
value: 'BR'
},
{
label: 'Argentina',
value: 'AR'
}
]
])
</script>
<template>
<B24Listbox :items="items" />
</template>
Multiple
Use the multiple prop to allow selecting multiple items. When enabled, the v-model will be an array.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox multiple :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox multiple :items="items" />
</template>
Value Key
You can choose to bind a single property of the object rather than the whole object by using the value-key prop. Defaults to undefined.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<B24Listbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<B24Listbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>
Filter
Use the filter prop to display a filter input or pass an object to customize the Input component. Defaults to false.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
},
{
label: 'Netherlands',
value: 'NL'
},
{
label: 'Poland',
value: 'PL'
}
])
</script>
<template>
<B24Listbox :filter="{
placeholder: 'Filter...'
}" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
},
{
label: 'Netherlands',
value: 'NL'
},
{
label: 'Poland',
value: 'PL'
}
])
</script>
<template>
<B24Listbox :filter="{
placeholder: 'Filter...'
}" :items="items" />
</template>
Selected Icon
Use the selected-icon prop to customize the icon when an item is selected.
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<B24Listbox v-model="value" :selected-icon="RocketIcon" value-key="value" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<B24Listbox v-model="value" :selected-icon="RocketIcon" value-key="value" :items="items" class="w-full" />
</template>
Size
Use the size prop to change the size of the Listbox.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox size="xl" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox size="xl" :items="items" />
</template>
Loading
Use the loading prop to display a loading indicator. Use the loading-icon prop to customize the icon.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
}
])
</script>
<template>
<B24Listbox loading :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
}
])
</script>
<template>
<B24Listbox loading :items="items" />
</template>
Disabled
Use the disabled prop to prevent any user interaction with the Listbox.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox disabled :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
value: 'FR'
},
{
label: 'Germany',
value: 'DE'
},
{
label: 'Italy',
value: 'IT'
},
{
label: 'Spain',
value: 'ES'
}
])
</script>
<template>
<B24Listbox disabled :items="items" />
</template>
Examples
With items type
You can use the type property with separator to display a separator between items or label to display a label.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[][]>([
[
{
type: 'label',
label: 'Fruits'
},
{
label: 'Apple'
},
{
label: 'Banana'
},
{
label: 'Blueberry'
},
{
label: 'Grapes'
},
{
label: 'Pineapple'
}
],
[
{
type: 'label',
label: 'Vegetables'
},
{
label: 'Aubergine'
},
{
label: 'Broccoli'
},
{
label: 'Carrot'
},
{
label: 'Courgette'
},
{
label: 'Leek'
}
]
])
</script>
<template>
<B24Listbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[][]>([
[
{
type: 'label',
label: 'Fruits'
},
{
label: 'Apple'
},
{
label: 'Banana'
},
{
label: 'Blueberry'
},
{
label: 'Grapes'
},
{
label: 'Pineapple'
}
],
[
{
type: 'label',
label: 'Vegetables'
},
{
label: 'Aubergine'
},
{
label: 'Broccoli'
},
{
label: 'Carrot'
},
{
label: 'Courgette'
},
{
label: 'Leek'
}
]
])
</script>
<template>
<B24Listbox :items="items" />
</template>
label items as group headings, pass an array of arrays so a label gets filtered out together with its group when searching.With icon in items
You can use the icon property to display an Icon inside the items.
With avatar in items
You can use the avatar property to display an Avatar inside the items.
With chip in items
You can use the chip property to display a Chip inside the items.
With description in items
You can use the description property to display additional text below the label.
<script setup lang="ts">
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
value: 'ES'
}
])
</script>
<template>
<B24Listbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@bitrix24/b24ui-nuxt'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
value: 'ES'
}
])
</script>
<template>
<B24Listbox :items="items" />
</template>
Control selected items
You can control the selected item by using the default-value prop or the v-model directive.
Control search term
Use the v-model:search-term directive to control the search term.
With ignore filter
Set the ignore-filter prop to true to disable the internal search and use your own search logic.
refDebounced to debounce the API calls.With filter fields
Use the filter-fields prop with an array of fields to filter on. Defaults to [labelKey].
With virtualization
Use the virtualize prop to enable virtualization for large lists as a boolean or an object with options like { estimateSize: 32, overscan: 12 }.
As a transfer list
You can compose two Listbox components with Button controls to build a transfer list pattern.
API
Props
Slots
Emits
Theme
export default {
slots: {
root: 'flex flex-col min-h-0 min-w-0 ring ring-inset ring-(--ui-color-design-outline-stroke) rounded-lg overflow-hidden outline-(--b24ui-border-color) has-focus-visible:outline-3 has-focus-visible:ring-(--b24ui-border-color)',
input: 'border-b border-(--ui-color-design-outline-stroke) has-focus-visible:border-(--b24ui-border-color)',
content: 'relative overflow-y-auto flex-1 max-h-60 scroll-py-1 focus:outline-none',
group: 'isolate',
label: 'w-full min-w-[195px] h-(--popup-window-delimiter-section-height) px-4.5 mt-(--menu-item-block-stack-space) flex flex-row rtl:flex-row-reverse items-center select-none outline-none whitespace-nowrap text-start text-(length:--ui-size-sm) text-legend font-(--ui-font-weight-normal) after:ms-[10px] after:block after:flex-1 after:min-w-[15px] after:h-px after:bg-(--ui-color-divider-vibrant-default)',
separator: 'my-2 mx-4.5 h-[1px] bg-(--ui-color-divider-vibrant-default)',
empty: 'py-2 select-none outline-none whitespace-nowrap text-center text-(length:--popup-window-delimiter-font-size)/(--ui-font-line-height-lg) text-legend font-(--ui-font-weight-normal)',
loading: 'flex items-center justify-center text-muted',
loadingIcon: 'shrink-0',
item: 'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-0 data-disabled:cursor-not-allowed data-disabled:opacity-75 text-default data-highlighted:not-data-disabled:text-label data-[state=checked]:text-label data-highlighted:not-data-disabled:before:bg-(--ui-color-base-black-fixed)/3 dark:data-highlighted:not-data-disabled:before:bg-(--ui-color-base-black-fixed) transition-colors before:transition-colors',
itemLeadingIcon: 'size-[25px] shrink-0 text-(--ui-color-base-5)',
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemLeadingChip: 'shrink-0',
itemLeadingChipSize: '',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate -mt-[6px] text-description text-(length:--ui-font-size-sm)',
itemTrailing: 'ml-auto rtl:ml-0 rtl:mr-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0 text-(--ui-color-accent-main-primary)'
},
variants: {
size: {
xss: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-[10px]',
loading: 'py-3',
loadingIcon: 'size-2',
item: 'p-1 text-[10px] gap-1',
itemLeadingIcon: 'size-3 mt-0.5',
itemLeadingAvatar: 'size-3 mt-0.5',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-3 mt-0.5',
itemLeadingChipSize: '2xs',
itemTrailingIcon: 'size-3 mt-0.5'
},
xs: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-[12px]',
loading: 'py-3',
loadingIcon: 'size-[12px]',
item: 'p-1 text-[12px] gap-1',
itemLeadingIcon: 'size-4 mt-0.5',
itemLeadingAvatar: 'size-4 mt-0.5',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-3 mt-0.5',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4 mt-0.5'
},
sm: {
label: 'p-1.5 text-[10px]/3 gap-1.5',
empty: 'py-4 text-[14px]',
loading: 'py-4',
loadingIcon: 'size-4',
item: 'p-1.5 text-[14px] gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatar: 'size-5',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4 mt-1',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-5'
},
md: {
label: 'px-4.5 py-1.5 text-xs gap-1.5',
empty: 'py-6 text-4',
loading: 'py-6',
loadingIcon: 'size-6',
item: 'px-4.5 py-1.5 text-4 gap-1.5',
itemLeadingIcon: 'size-6',
itemLeadingAvatar: 'size-6',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5 mt-1',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-6'
},
lg: {
label: 'p-2 text-xs gap-2',
empty: 'py-7 text-4',
loading: 'py-7',
loadingIcon: 'size-8',
item: 'p-2 text-4 gap-2',
itemLeadingIcon: 'size-7',
itemLeadingAvatar: 'size-7',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5 mt-1',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-6'
},
xl: {
label: 'p-2 text-4 gap-2',
empty: 'py-8 text-6',
loading: 'py-8',
loadingIcon: 'size-10',
item: 'p-2 text-6 gap-2',
itemLeadingIcon: 'size-7',
itemLeadingAvatar: 'size-7',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
itemDescription: 'text-4'
}
},
color: {
'air-primary': {
root: 'style-filled'
},
'air-primary-success': {
root: 'style-filled-success'
},
'air-primary-alert': {
root: 'style-filled-alert'
},
'air-primary-copilot': {
root: 'style-filled-copilot'
},
'air-primary-warning': {
root: 'style-filled-warning'
}
},
virtualize: {
true: {
content: 'p-1 isolate'
},
false: {
content: 'divide-y divide-(--ui-color-divider-default)'
}
},
disabled: {
true: {
root: 'cursor-not-allowed opacity-30'
}
},
highlight: {
true: 'ring ring-inset ring-(--b24ui-border-color)'
}
},
compoundVariants: [],
defaultVariants: {
color: 'air-primary',
size: 'md'
}
}