Listbox

ListboxGitHub
Eine auswählbare Liste von Elementen mit Suche, Virtualisierung und Rich Item Rendering.

Bearbeiten

Verwenden Sie die v-model-Direktive, um den Wert der Listbox zu steuern, oder die default-value-Prop, um den Anfangswert festzulegen, wenn Sie den Zustand nicht steuern müssen.

France
Germany
Italy
Spain
Netherlands
Poland
Belgium
Portugal
Austria
Sweden
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox v-model="value" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox v-model="value" :items="items" />
</template>

Items Bearbeiten

Verwenden Sie die items-prop als Array von Objekten mit den folgenden Eigenschaften:

FranceThe Hexagon
GermanyThe Federal Republic
ItalyThe Boot
SpainThe Bull Skin
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>

Sie können auch ein Array von Arrays an die items-Prop übergeben, um getrennte Gruppen von Elementen anzuzeigen.

France
Germany
Italy
Brazil
Argentina
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>

Mehrfach

Verwenden Sie die multiple-prop, um die Auswahl mehrerer Elemente zu ermöglichen. Wenn aktiviert, wird die v-model ein Array sein.

France
Germany
Italy
Spain
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox multiple :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox multiple :items="items" />
</template>

value Schlüsselwort

Sie können eine einzelne Eigenschaft des Objekts anstelle des gesamten Objekts binden, indem Sie die value-key-Prop verwenden.

France
Germany
Italy
Spain
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>

Filter (englisch)

Verwenden Sie die filter-Prop, um eine Filtereingabe anzuzeigen, oder übergeben Sie ein Objekt, um die Input-Komponente anzupassen.

France
Germany
Italy
Spain
Netherlands
Poland
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :filter="{
  placeholder: 'Filter...',
  icon: 'i-lucide-search'
}" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :filter="{
  placeholder: 'Filter...',
  icon: 'i-lucide-search'
}" :items="items" />
</template>

Selected Icon auswählen

Verwenden Sie die selected-icon prop, um das Symbol anzupassen, wenn ein Element ausgewählt ist. Standardmäßig i-lucide-check.

France
Germany
Italy
Spain
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox 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 '@nuxt/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>
  <UListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template>

x307xSize

Verwenden Sie die size-Prop, um die Größe der Listbox zu ändern.

France
Germany
Italy
Spain
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox size="xl" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox size="xl" :items="items" />
</template>

Loading (englisch)

Verwenden Sie die loading-prop, um eine Ladeanzeige anzuzeigen. Verwenden Sie die loading-icon-prop, um das Symbol anzupassen.

<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox loading :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox loading :items="items" />
</template>

Disabled (englisch)

Verwenden Sie die disabled-Prop, um Benutzerinteraktionen mit der Listbox zu verhindern.

France
Germany
Italy
Spain
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox disabled :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox disabled :items="items" />
</template>

Examples Bearbeiten

With items type (Deutsche Übersetzung)

Sie können die type-Eigenschaft mit separator verwenden, um ein Trennzeichen zwischen Elementen anzuzeigen, oder label, um eine Beschriftung anzuzeigen.

Fruits
Apple
Banana
Blueberry
Grapes
Pineapple
Vegetables
Aubergine
Broccoli
Carrot
Courgette
Leek
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
Wenn Sie label-Elemente als Gruppenüberschriften verwenden, übergeben Sie ein Array von Arrays, damit ein Label bei der Suche zusammen mit seiner Gruppe herausgefiltert wird.

With Icon in items (Deutsche Ausgabe)

Sie können die icon-Eigenschaft verwenden, um ein Icon innerhalb der Elemente anzuzeigen.

Backlog
Todo
In Progress
Done
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>

With avatar in items (Mit Avatar in Elementen)

Sie können die avatar-Eigenschaft verwenden, um ein Avatar in den Elementen anzuzeigen.

benjamincanac
HugoRCD
atinux
romhml
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items = ref<ListboxItem[]>([
  {
    label: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png'
    }
  },
  {
    label: 'HugoRCD',
    avatar: {
      src: 'https://github.com/HugoRCD.png'
    }
  },
  {
    label: 'atinux',
    avatar: {
      src: 'https://github.com/atinux.png'
    }
  },
  {
    label: 'romhml',
    avatar: {
      src: 'https://github.com/romhml.png'
    }
  }
])
</script>

<template>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'

const items = ref<ListboxItem[]>([
  {
    label: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png'
    }
  },
  {
    label: 'HugoRCD',
    avatar: {
      src: 'https://github.com/HugoRCD.png'
    }
  },
  {
    label: 'atinux',
    avatar: {
      src: 'https://github.com/atinux.png'
    }
  },
  {
    label: 'romhml',
    avatar: {
      src: 'https://github.com/romhml.png'
    }
  }
])
</script>

<template>
  <UListbox :items="items" />
</template>

Mit Chip in den Gegenständen

Sie können die chip-Eigenschaft verwenden, um ein Chip in den Elementen anzuzeigen.

bug
feature
enhancement
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items = ref<ListboxItem[]>([
  {
    label: 'bug',
    chip: {
      color: 'error'
    }
  },
  {
    label: 'feature',
    chip: {
      color: 'success'
    }
  },
  {
    label: 'enhancement',
    chip: {
      color: 'info'
    }
  }
])
</script>

<template>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'

const items = ref<ListboxItem[]>([
  {
    label: 'bug',
    chip: {
      color: 'error'
    }
  },
  {
    label: 'feature',
    chip: {
      color: 'success'
    }
  },
  {
    label: 'enhancement',
    chip: {
      color: 'info'
    }
  }
])
</script>

<template>
  <UListbox :items="items" />
</template>

With description in items (Beschreibung in Elementen)

Sie können die description-Eigenschaft verwenden, um zusätzlichen Text unterhalb der Beschriftung anzuzeigen.

FranceThe Hexagon
GermanyThe Federal Republic
ItalyThe Boot
SpainThe Bull Skin
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/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>
  <UListbox :items="items" />
</template>

Control selected item (s) Ausgewähltes Element

Sie können das ausgewählte Element mit der default-value-prop-oder der v-model-Direktive steuern.

France
Germany
Italy
Spain
Netherlands
Poland
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: 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' }
]

const value = ref<ListboxItem>(items[2]!)
</script>

<template>
  <UListbox
    v-model="value"
    :items="items"
    class="w-full"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'

const items: 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' }
]

const value = ref<ListboxItem>(items[2]!)
</script>

<template>
  <UListbox
    v-model="value"
    :items="items"
    class="w-full"
  />
</template>

Control Suchbegriff

Verwenden Sie die v-model:search-term-Direktive, um den Suchbegriff zu steuern.

France
<script setup lang="ts">
const searchTerm = ref('F')
const items = ref([
  { 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' }
])
const value = ref()
</script>

<template>
  <UListbox v-model="value" v-model:search-term="searchTerm" filter :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'

const searchTerm = ref('F')
const items = ref([
  { 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' }
])
const value = ref()
</script>

<template>
  <UListbox v-model="value" v-model:search-term="searchTerm" filter :items="items" class="w-full" />
</template>

With ignore filter (Filter ignorieren)

Setzen Sie die ignore-filter prop auf true, um die interne Suche zu deaktivieren und Ihre eigene Suchlogik zu verwenden.

No data
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'

const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'listbox-users-search',
  params: { q: searchTermDebounced },
  transform: (data: { id: number, name: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      value: String(user.id),
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    }))
  },
  immediate: false
})

onMounted(() => {
  execute()
})
</script>

<template>
  <UListbox
    v-model:search-term="searchTerm"
    :items="users || []"
    :filter="{
      icon: 'i-lucide-search',
      loading: status === 'pending'
    }"
    ignore-filter
    class="w-full"
  />
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { refDebounced } from '@vueuse/core'

const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'listbox-users-search',
  params: { q: searchTermDebounced },
  transform: (data: { id: number, name: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      value: String(user.id),
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    }))
  },
  immediate: false
})

onMounted(() => {
  execute()
})
</script>

<template>
  <UListbox
    v-model:search-term="searchTerm"
    :items="users || []"
    :filter="{
      icon: 'i-lucide-search',
      loading: status === 'pending'
    }"
    ignore-filter
    class="w-full"
  />
</template>
In diesem Beispiel wird refDebounced verwendet, um die API-Aufrufe zu entkräften.

With Filterfelder

Verwenden Sie die filter-fields-Prop mit einem Array von Feldern, um nach. Defaults auf [labelKey] zu filtern.

No data
<script setup lang="ts">
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'typicode-users-email',
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      email: user.email,
      value: String(user.id),
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    }))
  },
  immediate: false
})

onMounted(() => {
  execute()
})
</script>

<template>
  <UListbox
    :items="users || []"
    :loading="status === 'pending'"
    :filter-fields="['label', 'email']"
    filter
    class="w-full"
  >
    <template #item-label="{ item }">
      {{ item.label }}

      <span class="text-muted">
        {{ item.email }}
      </span>
    </template>
  </UListbox>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'typicode-users-email',
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      email: user.email,
      value: String(user.id),
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    }))
  },
  immediate: false
})

onMounted(() => {
  execute()
})
</script>

<template>
  <UListbox
    :items="users || []"
    :loading="status === 'pending'"
    :filter-fields="['label', 'email']"
    filter
    class="w-full"
  >
    <template #item-label="{ item }">
      {{ item.label }}

      <span class="text-muted">
        {{ item.email }}
      </span>
    </template>
  </UListbox>
</template>

Mit Virtualisierung

Verwenden Sie die virtualize-Prop, um die Virtualisierung für große Listen als Boolean oder ein Objekt mit Optionen wie { estimateSize: 32, overscan: 12 } zu aktivieren.

<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = Array.from({ length: 1000 }, (_, i) => ({
  label: `Item ${i + 1}`,
  icon: 'i-lucide-file',
  value: i + 1
}))

const value = ref<ListboxItem[]>([])
</script>

<template>
  <UListbox
    v-model="value"
    :items="items"
    multiple
    virtualize
    class="w-full"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'

const items: ListboxItem[] = Array.from({ length: 1000 }, (_, i) => ({
  label: `Item ${i + 1}`,
  icon: 'i-lucide-file',
  value: i + 1
}))

const value = ref<ListboxItem[]>([])
</script>

<template>
  <UListbox
    v-model="value"
    :items="items"
    multiple
    virtualize
    class="w-full"
  />
</template>

As eine Übertragungsliste

Sie können zwei Listbox-Komponenten mit Button-Steuerelementen zusammenstellen, um ein Übertragungslistenmuster zu erstellen.

Available
France
Germany
Italy
Spain
Netherlands
Poland
Belgium
Portugal
Selected
No data
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'

const items: 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' }
]

const targetItems = ref<ListboxItem[]>([])
const sourceSelection = ref<ListboxItem[]>([])
const targetSelection = ref<ListboxItem[]>([])

const sourceItems = computed(() => items.filter(item => !targetItems.value.some(t => t.value === item.value)))

function transferSelected() {
  targetItems.value = [...targetItems.value, ...sourceSelection.value]
  sourceSelection.value = []
}

function removeSelected() {
  targetItems.value = targetItems.value.filter(item => !targetSelection.value.some(t => t.value === item.value))
  targetSelection.value = []
}
</script>

<template>
  <div class="flex items-stretch gap-4 w-full">
    <div class="flex flex-col flex-1 gap-1">
      <span class="text-sm font-medium text-highlighted">Available</span>

      <UListbox
        v-model="sourceSelection"
        :items="sourceItems"
        multiple
        filter
        class="size-full"
      />
    </div>

    <div class="flex flex-col items-center justify-center gap-1">
      <UButton
        icon="i-lucide-chevron-right"
        color="neutral"
        variant="outline"
        :disabled="!sourceSelection.length"
        @click="transferSelected"
      />
      <UButton
        icon="i-lucide-chevron-left"
        color="neutral"
        variant="outline"
        :disabled="!targetSelection.length"
        @click="removeSelected"
      />
    </div>

    <div class="flex flex-col flex-1 gap-1">
      <span class="text-sm font-medium text-highlighted">Selected</span>

      <UListbox
        v-model="targetSelection"
        :items="targetItems"
        multiple
        filter
        class="size-full"
      />
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ListboxItem } from '@nuxt/ui'

const items: 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' }
]

const targetItems = ref<ListboxItem[]>([])
const sourceSelection = ref<ListboxItem[]>([])
const targetSelection = ref<ListboxItem[]>([])

const sourceItems = computed(() => items.filter(item => !targetItems.value.some(t => t.value === item.value)))

function transferSelected() {
  targetItems.value = [...targetItems.value, ...sourceSelection.value]
  sourceSelection.value = []
}

function removeSelected() {
  targetItems.value = targetItems.value.filter(item => !targetSelection.value.some(t => t.value === item.value))
  targetSelection.value = []
}
</script>

<template>
  <div class="flex items-stretch gap-4 w-full">
    <div class="flex flex-col flex-1 gap-1">
      <span class="text-sm font-medium text-highlighted">Available</span>

      <UListbox
        v-model="sourceSelection"
        :items="sourceItems"
        multiple
        filter
        class="size-full"
      />
    </div>

    <div class="flex flex-col items-center justify-center gap-1">
      <UButton
        icon="i-lucide-chevron-right"
        color="neutral"
        variant="outline"
        :disabled="!sourceSelection.length"
        @click="transferSelected"
      />
      <UButton
        icon="i-lucide-chevron-left"
        color="neutral"
        variant="outline"
        :disabled="!targetSelection.length"
        @click="removeSelected"
      />
    </div>

    <div class="flex flex-col flex-1 gap-1">
      <span class="text-sm font-medium text-highlighted">Selected</span>

      <UListbox
        v-model="targetSelection"
        :items="targetItems"
        multiple
        filter
        class="size-full"
      />
    </div>
  </div>
</template>

API (englisch)

Props Bearbeiten

Prop Default Type
as
'div'
any

The element or component this component should render as.

id
string
color
'primary'
"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"
size
'md'
"sm" | "md" | "xs" | "lg" | "xl"
items
T

The 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 v-model.

modelModifiers
Mod
defaultValue
_Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>

The default value when not controlled.

multiple
false
M

Whether multiple items can be selected.

valueKey
undefined
VK

When items is an array of objects, select the field to use as the value instead of the object itself.

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
any

The 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. { placeholder: 'Search...', variant: 'none' }

filterFields
[labelKey]
string[]

The fields to filter by.

ignoreFilter
false
boolean

When true, disable the default filters, useful for custom filtering (useAsyncData, useFetch, etc.).

selectedIcon
appConfig.ui.icons.check
any

The icon displayed when an item is selected.

virtualize
false
boolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefined

Enable 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): boolean

Use 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 true, prevents the user from interacting with listbox

highlightOnHover
true
boolean

When true, hover over item will trigger highlight

name
string

The name of the field. Submitted with its owning form as part of a name/value pair.

orientation
"vertical" | "horizontal"

The orientation of the listbox.
Mainly so arrow navigation is done accordingly (left & right vs. up & down)

required
boolean

When true, indicates that the user must set the value before the owning form can be submitted.

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; }

Slots Bearbeiten

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; }

Emits (englisch)

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]

Theme (englisch)

app.config.ts
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'
          },
          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'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/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'
              },
              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'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.

Changelog Bearbeiten

No recent changes