Use a diretiva v-model para controlar o valor do Listbox ou a prop default-value para definir o valor inicial quando você não precisa controlar o estado.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
},
{
label: 'Belgium',
icon: 'i-lucide-map-pin',
value: 'BE'
},
{
label: 'Portugal',
icon: 'i-lucide-map-pin',
value: 'PT'
},
{
label: 'Austria',
icon: 'i-lucide-map-pin',
value: 'AT'
},
{
label: 'Sweden',
icon: 'i-lucide-map-pin',
value: 'SE'
}
])
const value = ref({
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
})
</script>
<template>
<NListbox v-model="value" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
},
{
label: 'Belgium',
icon: 'i-lucide-map-pin',
value: 'BE'
},
{
label: 'Portugal',
icon: 'i-lucide-map-pin',
value: 'PT'
},
{
label: 'Austria',
icon: 'i-lucide-map-pin',
value: 'AT'
},
{
label: 'Sweden',
icon: 'i-lucide-map-pin',
value: 'SE'
}
])
const value = ref({
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
})
</script>
<template>
<NListbox v-model="value" :items="items" />
</template>
Use a prop items como um array de objetos com as seguintes propriedades:
label?: stringdescription?: stringtype?: "label" | "separator" | "item"icon?: stringavatar?: AvatarPropschip?: ChipPropsdisabled?: booleanonSelect?: (e: Event) => voidclass?: anyui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, ... }<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
Você também pode passar um array de arrays para a prop items para exibir grupos separados de itens.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
}
],
[
{
label: 'Brazil',
icon: 'i-lucide-map-pin',
value: 'BR'
},
{
label: 'Argentina',
icon: 'i-lucide-map-pin',
value: 'AR'
}
]
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
}
],
[
{
label: 'Brazil',
icon: 'i-lucide-map-pin',
value: 'BR'
},
{
label: 'Argentina',
icon: 'i-lucide-map-pin',
value: 'AR'
}
]
])
</script>
<template>
<NListbox :items="items" />
</template>
Use a prop multiple para permitir a seleção de vários itens. Quando habilitada, o v-model será um array.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox multiple :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox multiple :items="items" />
</template>
Você pode optar por vincular uma única propriedade do objeto em vez do objeto inteiro usando a prop value-key. O padrão é undefined.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<NListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<NListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>
Use a prop filter para exibir um campo de filtro ou passe um objeto para personalizar o componente Input. O padrão é false.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
}
])
</script>
<template>
<NListbox :filter="{
placeholder: 'Filter...',
icon: 'i-lucide-search'
}" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
}
])
</script>
<template>
<NListbox :filter="{
placeholder: 'Filter...',
icon: 'i-lucide-search'
}" :items="items" />
</template>
Use a prop selected-icon para personalizar o ícone quando um item é selecionado. O padrão é i-lucide-check.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<NListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<NListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template>
Use a prop size para alterar o tamanho do Listbox.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox size="xl" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox size="xl" :items="items" />
</template>
Use a prop loading para exibir um indicador de carregamento. Use a prop loading-icon para personalizar o ícone.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
}
])
</script>
<template>
<NListbox loading :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
}
])
</script>
<template>
<NListbox loading :items="items" />
</template>
Use a prop disabled para impedir qualquer interação do usuário com o Listbox.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox disabled :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox disabled :items="items" />
</template>
Você pode usar a propriedade type com separator para exibir um separador entre os itens ou label para exibir um rótulo.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
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>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
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>
<NListbox :items="items" />
</template>
label como cabeçalhos de grupo, passe um array de arrays para que um rótulo seja filtrado junto com o grupo dele durante a busca.Você pode usar a propriedade icon para exibir um Icon dentro dos itens.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'Backlog',
icon: 'i-lucide-circle-help',
value: 'backlog'
},
{
label: 'Todo',
icon: 'i-lucide-circle-plus',
value: 'todo'
},
{
label: 'In Progress',
icon: 'i-lucide-circle-arrow-up',
value: 'in_progress'
},
{
label: 'Done',
icon: 'i-lucide-circle-check',
value: 'done'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'Backlog',
icon: 'i-lucide-circle-help',
value: 'backlog'
},
{
label: 'Todo',
icon: 'i-lucide-circle-plus',
value: 'todo'
},
{
label: 'In Progress',
icon: 'i-lucide-circle-arrow-up',
value: 'in_progress'
},
{
label: 'Done',
icon: 'i-lucide-circle-check',
value: 'done'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
Você pode usar a propriedade avatar para exibir um Avatar dentro dos itens.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png'
}
}
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png'
}
}
])
</script>
<template>
<NListbox :items="items" />
</template>
Você pode usar a propriedade chip para exibir um Chip dentro dos itens.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
chip: {
color: 'info'
}
}
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
chip: {
color: 'info'
}
}
])
</script>
<template>
<NListbox :items="items" />
</template>
Você pode usar a propriedade description para exibir um texto adicional abaixo do rótulo.
<script setup lang="ts">
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nitro/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<NListbox :items="items" />
</template>
Você pode controlar o item selecionado usando a prop default-value ou a diretiva v-model.
Use a diretiva v-model:search-term para controlar o termo de busca.
Defina a prop ignore-filter como true para desabilitar a busca interna e usar sua própria lógica de busca.
refDebounced para aplicar debounce nas chamadas de API.Use a prop filter-fields com um array de campos para filtrar. O padrão é [labelKey].
Use a prop virtualize para habilitar a virtualização em listas grandes, como um booleano ou um objeto com opções como { estimateSize: 32, overscan: 12 }.
Você pode compor dois componentes Listbox com controles de Button para construir um padrão de lista de transferência.
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
id | string | |
color | 'primary' | "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral" |
size | 'md' | "sm" | "md" | "xs" | "lg" | "xl" |
items | TThe items to display in the list. | |
modelValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>The controlled value of the Listbox. Can be bound with | |
modelModifiers | Mod | |
defaultValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>The default value when not controlled. | |
multiple | false | MWhether multiple items can be selected. |
valueKey | undefined | VKWhen |
labelKey | 'label' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the label from the item. |
descriptionKey | 'description' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the description from the item. |
loading | boolean Whether the list is in a loading state. | |
loadingIcon | appConfig.ui.icons.loading | anyThe icon displayed when loading. |
filter | false | boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue"> Whether to display a filter input or not.
Can be an object to pass additional props to the input.
|
filterFields | [labelKey] | string[]The fields to filter by. |
ignoreFilter | false | boolean When |
selectedIcon | appConfig.ui.icons.check | anyThe icon displayed when an item is selected. |
virtualize | false | boolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefinedEnable virtualization for large lists. |
highlight | boolean Highlight the ring color like a focus state. | |
autofocus | boolean | |
autofocusDelay | 0 | number |
by | string | (a: AcceptableValue, b: AcceptableValue): booleanUse this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | |
disabled | boolean When | |
highlightOnHover | true | boolean When |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
orientation | "vertical" | "horizontal"The orientation of the listbox. | |
required | boolean When | |
selectionBehavior | 'toggle' | "replace" | "toggle"How multiple selection should behave in the collection. |
searchTerm | '' | string |
ui | { root?: SlotClass; input?: SlotClass; content?: SlotClass; group?: SlotClass; label?: SlotClass; separator?: SlotClass; empty?: SlotClass; loading?: SlotClass; loadingIcon?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemLeadingChip?: SlotClass; itemLeadingChipSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemDescription?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; } |
| Slot | Type |
|---|---|
loading | {} |
empty | { searchTerm: string; } |
item | { item: NestedItem<T>; index: number; ui: object; } |
item-leading | { item: NestedItem<T>; index: number; ui: object; } |
item-label | { item: NestedItem<T>; index: number; } |
item-description | { item: NestedItem<T>; index: number; } |
item-trailing | { item: NestedItem<T>; index: number; ui: object; } |
| Event | Type |
|---|---|
entryFocus | [event: CustomEvent<any>] |
highlight | [payload: { ref: HTMLElement; value: AcceptableValue; } | undefined] |
leave | [event: Event] |
change | [event: Event] |
update:modelValue | [value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>] |
update:searchTerm | [value: string] |
export default defineAppConfig({
ui: {
listbox: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 ring ring-inset ring-default rounded-lg overflow-hidden',
input: 'border-b border-default',
content: 'relative overflow-y-auto flex-1 max-h-60 scroll-py-1 focus:outline-none',
group: 'p-1 isolate',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
empty: 'text-center text-muted',
loading: 'flex items-center justify-center text-muted',
loadingIcon: 'animate-spin shrink-0',
item: [
'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75 text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'shrink-0 text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
'transition-colors'
],
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemLeadingChip: 'shrink-0',
itemLeadingChipSize: '',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0'
},
variants: {
size: {
xs: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-xs',
loading: 'py-3',
loadingIcon: 'size-4',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
sm: {
label: 'p-1.5 text-[10px]/3 gap-1.5',
empty: 'py-4 text-xs',
loading: 'py-4',
loadingIcon: 'size-4',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
md: {
label: 'p-1.5 text-xs gap-1.5',
empty: 'py-6 text-sm',
loading: 'py-6',
loadingIcon: 'size-5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
lg: {
label: 'p-2 text-xs gap-2',
empty: 'py-7 text-sm',
loading: 'py-7',
loadingIcon: 'size-5',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
xl: {
label: 'p-2 text-sm gap-2',
empty: 'py-8 text-base',
loading: 'py-8',
loadingIcon: 'size-6',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
itemDescription: 'text-sm'
}
},
color: {
primary: {
root: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
secondary: {
root: 'outline-secondary/25 has-focus-visible:outline-3 has-focus-visible:ring-secondary'
},
accent: {
root: 'outline-accent/25 has-focus-visible:outline-3 has-focus-visible:ring-accent'
},
success: {
root: 'outline-success/25 has-focus-visible:outline-3 has-focus-visible:ring-success'
},
info: {
root: 'outline-info/25 has-focus-visible:outline-3 has-focus-visible:ring-info'
},
warning: {
root: 'outline-warning/25 has-focus-visible:outline-3 has-focus-visible:ring-warning'
},
error: {
root: 'outline-error/25 has-focus-visible:outline-3 has-focus-visible:ring-error'
},
neutral: {
root: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
}
},
virtualize: {
true: {
content: 'p-1 isolate'
},
false: {
content: 'divide-y divide-default'
}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed'
}
},
highlight: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
highlight: true,
class: {
root: 'ring ring-inset ring-primary'
}
},
{
color: 'neutral',
highlight: true,
class: {
root: 'ring ring-inset ring-inverted'
}
}
],
defaultVariants: {
color: 'primary',
size: 'md'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
listbox: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 ring ring-inset ring-default rounded-lg overflow-hidden',
input: 'border-b border-default',
content: 'relative overflow-y-auto flex-1 max-h-60 scroll-py-1 focus:outline-none',
group: 'p-1 isolate',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
empty: 'text-center text-muted',
loading: 'flex items-center justify-center text-muted',
loadingIcon: 'animate-spin shrink-0',
item: [
'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75 text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'shrink-0 text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
'transition-colors'
],
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemLeadingChip: 'shrink-0',
itemLeadingChipSize: '',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0'
},
variants: {
size: {
xs: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-xs',
loading: 'py-3',
loadingIcon: 'size-4',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
sm: {
label: 'p-1.5 text-[10px]/3 gap-1.5',
empty: 'py-4 text-xs',
loading: 'py-4',
loadingIcon: 'size-4',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
md: {
label: 'p-1.5 text-xs gap-1.5',
empty: 'py-6 text-sm',
loading: 'py-6',
loadingIcon: 'size-5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
lg: {
label: 'p-2 text-xs gap-2',
empty: 'py-7 text-sm',
loading: 'py-7',
loadingIcon: 'size-5',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
xl: {
label: 'p-2 text-sm gap-2',
empty: 'py-8 text-base',
loading: 'py-8',
loadingIcon: 'size-6',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
itemDescription: 'text-sm'
}
},
color: {
primary: {
root: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
secondary: {
root: 'outline-secondary/25 has-focus-visible:outline-3 has-focus-visible:ring-secondary'
},
accent: {
root: 'outline-accent/25 has-focus-visible:outline-3 has-focus-visible:ring-accent'
},
success: {
root: 'outline-success/25 has-focus-visible:outline-3 has-focus-visible:ring-success'
},
info: {
root: 'outline-info/25 has-focus-visible:outline-3 has-focus-visible:ring-info'
},
warning: {
root: 'outline-warning/25 has-focus-visible:outline-3 has-focus-visible:ring-warning'
},
error: {
root: 'outline-error/25 has-focus-visible:outline-3 has-focus-visible:ring-error'
},
neutral: {
root: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
}
},
virtualize: {
true: {
content: 'p-1 isolate'
},
false: {
content: 'divide-y divide-default'
}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed'
}
},
highlight: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
highlight: true,
class: {
root: 'ring ring-inset ring-primary'
}
},
{
color: 'neutral',
highlight: true,
class: {
root: 'ring ring-inset ring-inverted'
}
}
],
defaultVariants: {
color: 'primary',
size: 'md'
}
}
}
})
]
})