Inputmenu hinzufügen
Bearbeiten
Verwenden Sie die Direktive v-model, um den Wert des InputMenu zu steuern, oder die default-value prop, um den Anfangswert festzulegen, wenn Sie den Zustand nicht steuern müssen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template>Input, um die Vorteile der Komponente Combobox von Reka UI zu nutzen, die Autocomplete-Funktionen bietet.SelectMenu, verwendet jedoch eine Eingabe anstelle einer Auswahl.Items Bearbeiten
Verwenden Sie die items-prop als Array von Strings, Zahlen oder Booleans:
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template>Sie können auch ein Array von Objekten mit den folgenden Eigenschaften übergeben:
label?: string(nicht vorhanden) 0555xtype?: "label" | "separator" | "item"|icon?: string) xph0667x ) xph06667x xph0667x {lang="ts-type"}xx0667xxx066x06)avatar?: AvatarProps)x074xx07x07x07xph07x07x07x07xx07x07x07x07x07x07x07x07x07xx07x07x07x07x07x07x07x07x07x07x07x07x07x07x007x07x007x07x007x07x007x07x007x007x007x07x0007x007x00007x07x000000000000000000000000000000000000000000000007 08.07.2018 00:28 - 07:28 00:28:28:28 00:28:28:28:28disabled?: boolean(englisch)onSelect?: (e: Event) => void(nicht vorhanden)class?: any(nicht vorhanden)ui?: { tagsItem?: ClassNameValue, tagsItemText?: ClassNameValue, tagsItemDelete?: ClassNameValue, tagsItemDeleteIcon?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }(nicht vorhanden)
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
{
label: 'Backlog'
},
{
label: 'Todo'
},
{
label: 'In Progress'
},
{
label: 'Done'
}
])
const value = ref({
label: 'Todo'
})
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
{
label: 'Backlog'
},
{
label: 'Todo'
},
{
label: 'In Progress'
},
{
label: 'Done'
}
])
const value = ref({
label: 'Todo'
})
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template>Sie können auch ein Array von Arrays an die items-prop übergeben, um getrennte Gruppen von Elementen anzuzeigen.
<script setup lang="ts">
const items = ref([
['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple'],
['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
])
const value = ref('Apple')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref([
['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple'],
['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
])
const value = ref('Apple')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template>value Schlüssel
Sie können eine einzelne Eigenschaft des Objekts anstelle des gesamten Objekts binden, indem Sie die value-key-Prop verwenden.
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
{
label: 'Backlog',
id: 'backlog'
},
{
label: 'Todo',
id: 'todo'
},
{
label: 'In Progress',
id: 'in_progress'
},
{
label: 'Done',
id: 'done'
}
])
const value = ref('todo')
</script>
<template>
<UInputMenu v-model="value" value-key="id" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
{
label: 'Backlog',
id: 'backlog'
},
{
label: 'Todo',
id: 'todo'
},
{
label: 'In Progress',
id: 'in_progress'
},
{
label: 'Done',
id: 'done'
}
])
const value = ref('todo')
</script>
<template>
<UInputMenu v-model="value" value-key="id" :items="items" />
</template>by-prop, um Objekte durch ein Feld anstelle eines Verweises zu vergleichen, wenn die model-value ein Objekt ist.multiple ist ein
Verwenden Sie die multiple-prop, um mehrere Auswahlen zu ermöglichen, die ausgewählten Elemente werden als Tags angezeigt.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref(['Backlog', 'Todo'])
</script>
<template>
<UInputMenu v-model="value" multiple :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref(['Backlog', 'Todo'])
</script>
<template>
<UInputMenu v-model="value" multiple :items="items" />
</template>default-value-prop-oder die v-model-Direktive übergeben.Delete Icon löschen
Verwenden Sie mit multiple die delete-icon-Prop, um das Löschen von Icon in den Tags anzupassen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref(['Backlog', 'Todo'])
</script>
<template>
<UInputMenu v-model="value" multiple delete-icon="i-lucide-trash" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref(['Backlog', 'Todo'])
</script>
<template>
<UInputMenu v-model="value" multiple delete-icon="i-lucide-trash" :items="items" />
</template>Platzhalter
Verwenden Sie die placeholder-Prop, um einen Platzhaltertext festzulegen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>
<template>
<UInputMenu placeholder="Select status" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>
<template>
<UInputMenu placeholder="Select status" :items="items" />
</template>Mode: badge{label="4.8+" class="align-text-top"} (englisch)
Setzen Sie die mode-prop auf autocomplete, um das Eingabemenü in eine Freiform-Texteingabe mit Vorschlägen zu verwandeln. Die modelValue wird zum Eingabetext (string) anstelle eines ausgewählten Elements.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('')
</script>
<template>
<UInputMenu
v-model="value"
mode="autocomplete"
:items="items"
:trailing-icon="false"
:content="{ hideWhenEmpty: true }"
placeholder="Type a status..."
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('')
</script>
<template>
<UInputMenu
v-model="value"
mode="autocomplete"
:items="items"
:trailing-icon="false"
:content="{ hideWhenEmpty: true }"
placeholder="Type a status..."
/>
</template>
mode gleich autocomplete ist, sind multiple, by, resetSearchTermOnSelect und resetModelValueOnClear nicht anwendbar.content.hideWhenEmpty-Prop, um das Menü auszublenden, wenn es keine passenden Vorschläge gibt.Content Inhalt
Verwenden Sie die content-Prop, um zu steuern, wie der InputMenu-Inhalt gerendert wird, z. B. align oder side.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="value"
:content="{
align: 'center',
side: 'bottom',
sideOffset: 8
}"
:items="items"
/>
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="value"
:content="{
align: 'center',
side: 'bottom',
sideOffset: 8
}"
:items="items"
/>
</template>Pfeil
Verwenden Sie die arrow-Prop, um einen Pfeil im Eingabemenü anzuzeigen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" arrow :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" arrow :items="items" />
</template>Color Bearbeiten
Verwenden Sie die color prop, um die Ringfarbe zu ändern, wenn das Eingabemenü fokussiert ist.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" color="neutral" highlight :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" color="neutral" highlight :items="items" />
</template>highlight-prop wird hier verwendet, um den Fokuszustand anzuzeigen. Es wird intern verwendet, wenn ein Validierungsfehler auftritt.Variant Bearbeiten
Verwenden Sie die variant-prop, um die Variante des InputMenu zu ändern.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" color="neutral" variant="subtle" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" color="neutral" variant="subtle" :items="items" />
</template>Size Bearbeiten
Verwenden Sie die size-prop, um die Größe des Eingabemenüs zu ändern.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" size="xl" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" size="xl" :items="items" />
</template>Icon (englisch)
Verwenden Sie die icon-Prop, um ein Icon innerhalb des Eingabemenüs anzuzeigen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" icon="i-lucide-search" size="md" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" icon="i-lucide-search" size="md" :items="items" />
</template>Trailing Icon (Deutsche Übersetzung)
Verwenden Sie die trailing-icon-Prop, um die folgende Icon anzupassen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" trailing-icon="i-lucide-arrow-down" size="md" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" trailing-icon="i-lucide-arrow-down" size="md" :items="items" />
</template>app.config.ts unter der ui.icons.chevronDown-Taste anpassen.vite.config.ts unter ui.icons.chevronDown Schlüssel anpassen.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.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" selected-icon="i-lucide-flame" size="md" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" selected-icon="i-lucide-flame" size="md" :items="items" />
</template>Clear: badge{label="4.4+" class="align-text-top"} (Deutsche Übersetzung)
Verwenden Sie die clear-Prop, um eine Schaltfläche zum Löschen anzuzeigen, wenn ein Wert ausgewählt ist.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" clear :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" clear :items="items" />
</template>Clear Icon: badge{label="4.4+" class="align-text-top"} (Deutsche Ausgabe)
Verwenden Sie die clear-icon-Prop, um die Clear-Taste Icon. Defaults auf i-lucide-x.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" clear clear-icon="i-lucide-trash" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" clear clear-icon="i-lucide-trash" :items="items" />
</template>vite.config.ts unter dem ui.icons.close-Schlüssel anpassen.Avatar (englisch)
Verwenden Sie die avatar-Prop, um ein Avatar innerhalb des Eingabemenüs anzuzeigen.
<script setup lang="ts">
const items = ref(['Nuxt', 'NuxtHub', 'NuxtLabs', 'Nuxt Modules', 'Nuxt Community'])
const value = ref('Nuxt')
</script>
<template>
<UInputMenu
v-model="value"
:avatar="{
src: 'https://github.com/nuxt.png',
loading: 'lazy'
}"
:items="items"
/>
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Nuxt', 'NuxtHub', 'NuxtLabs', 'Nuxt Modules', 'Nuxt Community'])
const value = ref('Nuxt')
</script>
<template>
<UInputMenu
v-model="value"
:avatar="{
src: 'https://github.com/nuxt.png',
loading: 'lazy'
}"
:items="items"
/>
</template>Loading (nicht verfügbar)
Verwenden Sie die loading-Prop, um ein Ladesymbol im InputMenu anzuzeigen.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" loading :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" loading :items="items" />
</template>Loading Icon (englisch)
Verwenden Sie die loading-icon-Prop, um das Ladesymbol anzupassen. Standardmäßig i-lucide-loader-circle.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" loading loading-icon="i-lucide-loader" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" loading loading-icon="i-lucide-loader" :items="items" />
</template>Disabled (nicht verfügbar)
Verwenden Sie die disabled-Prop, um das Eingabemenü zu deaktivieren.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>
<template>
<UInputMenu disabled placeholder="Select status" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>
<template>
<UInputMenu disabled placeholder="Select status" :items="items" />
</template>Beispiele
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.
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
[
{
type: 'label',
label: 'Fruits'
},
'Apple',
'Banana',
'Blueberry',
'Grapes',
'Pineapple'
],
[
{
type: 'label',
label: 'Vegetables'
},
'Aubergine',
'Broccoli',
'Carrot',
'Courgette',
'Leek'
]
])
const value = ref('Apple')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem } from '@nuxt/ui'
const items = ref<InputMenuItem[]>([
[
{
type: 'label',
label: 'Fruits'
},
'Apple',
'Banana',
'Blueberry',
'Grapes',
'Pineapple'
],
[
{
type: 'label',
label: 'Vegetables'
},
'Aubergine',
'Broccoli',
'Carrot',
'Courgette',
'Leek'
]
])
const value = ref('Apple')
</script>
<template>
<UInputMenu v-model="value" :items="items" />
</template>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 Übersetzung)
Sie können die icon-Eigenschaft verwenden, um ein Icon innerhalb der Elemente anzuzeigen.
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'Backlog',
value: 'backlog',
icon: 'i-lucide-circle-help'
},
{
label: 'Todo',
value: 'todo',
icon: 'i-lucide-circle-plus'
},
{
label: 'In Progress',
value: 'in_progress',
icon: 'i-lucide-circle-arrow-up'
},
{
label: 'Done',
value: 'done',
icon: 'i-lucide-circle-check'
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :icon="value?.icon" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'Backlog',
value: 'backlog',
icon: 'i-lucide-circle-help'
},
{
label: 'Todo',
value: 'todo',
icon: 'i-lucide-circle-plus'
},
{
label: 'In Progress',
value: 'in_progress',
icon: 'i-lucide-circle-arrow-up'
},
{
label: 'Done',
value: 'done',
icon: 'i-lucide-circle-check'
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :icon="value?.icon" :items="items" />
</template>
#leading-Steckplatz verwenden, um das ausgewählte Symbol anzuzeigen.With avatar in items (mit Avatar in Elementen)
Sie können die avatar-Eigenschaft verwenden, um ein Avatar in den Elementen anzuzeigen.
<script setup lang="ts">
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'benjamincanac',
value: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png',
alt: 'benjamincanac',
loading: 'lazy' as const
}
},
{
label: 'HugoRCD',
value: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png',
alt: 'HugoRCD',
loading: 'lazy' as const
}
},
{
label: 'atinux',
value: 'atinux',
avatar: {
src: 'https://github.com/atinux.png',
alt: 'atinux',
loading: 'lazy' as const
}
},
{
label: 'romhml',
value: 'romhml',
avatar: {
src: 'https://github.com/romhml.png',
alt: 'romhml',
loading: 'lazy' as const
}
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :avatar="value?.avatar" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem } from '@nuxt/ui'
const items = ref([
{
label: 'benjamincanac',
value: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png',
alt: 'benjamincanac',
loading: 'lazy' as const
}
},
{
label: 'HugoRCD',
value: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png',
alt: 'HugoRCD',
loading: 'lazy' as const
}
},
{
label: 'atinux',
value: 'atinux',
avatar: {
src: 'https://github.com/atinux.png',
alt: 'atinux',
loading: 'lazy' as const
}
},
{
label: 'romhml',
value: 'romhml',
avatar: {
src: 'https://github.com/romhml.png',
alt: 'romhml',
loading: 'lazy' as const
}
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :avatar="value?.avatar" :items="items" />
</template>
#leading-slot verwenden, um den ausgewählten avatar anzuzeigen.With Chip in items (Deutsche Ausgabe)
Sie können die chip-Eigenschaft verwenden, um ein Chip in den Elementen anzuzeigen.
<script setup lang="ts">
import type { InputMenuItem, ChipProps } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
}
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :items="items">
<template #leading="{ modelValue, ui }">
<UChip
v-if="modelValue"
v-bind="modelValue.chip"
inset
standalone
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:class="ui.itemLeadingChip()"
/>
</template>
</UInputMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { InputMenuItem, ChipProps } from '@nuxt/ui'
const items = ref([
{
label: 'bug',
value: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
value: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
value: 'enhancement',
chip: {
color: 'info'
}
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>
<template>
<UInputMenu v-model="value" :items="items">
<template #leading="{ modelValue, ui }">
<UChip
v-if="modelValue"
v-bind="modelValue.chip"
inset
standalone
:size="(ui.itemLeadingChipSize() as ChipProps['size'])"
:class="ui.itemLeadingChip()"
/>
</template>
</UInputMenu>
</template>
#leading-Slot verwendet, um den ausgewählten Chip anzuzeigen.Control im offenen Zustand
Sie können den offenen Zustand mit der default-open-prop-oder der v-model:open-Anweisung steuern.
<script setup lang="ts">
const open = ref(false)
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<UInputMenu v-model="value" v-model:open="open" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<UInputMenu v-model="value" v-model:open="open" :items="items" />
</template>
defineShortcuts das Eingabemenü umschalten, indem Sie: kbd{value="O"} drücken.Control Open State bei Fokus
Sie können die open-on-focus oder open-on-click props verwenden, um das Menü zu öffnen, wenn die Eingabe fokussiert oder geklickt wird.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const selected = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="selected"
:items="items"
open-on-focus
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const selected = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="selected"
:items="items"
open-on-focus
/>
</template>
Control Suchbegriffe
Verwenden Sie die v-model:search-term-Direktive, um den Suchbegriff zu steuern.
<script setup lang="ts">
const searchTerm = ref('D')
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" v-model:search-term="searchTerm" :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
const searchTerm = ref('D')
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu v-model="value" v-model:search-term="searchTerm" :items="items" />
</template>
Mit rotierendem Icon
Hier ist ein Beispiel mit einem rotierenden Symbol, das den geöffneten Zustand des InputMenu anzeigt.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="value"
:items="items"
:ui="{
trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200'
}"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>
<template>
<UInputMenu
v-model="value"
:items="items"
:ui="{
trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200'
}"
/>
</template>
With Element erstellen
Verwenden Sie die create-item-Prop, um Benutzern das Hinzufügen benutzerdefinierter Werte zu ermöglichen, die nicht in den vordefinierten Optionen enthalten sind.
<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
function onCreate(item: string) {
items.value.push(item)
value.value = item
}
</script>
<template>
<UInputMenu
v-model="value"
create-item
:items="items"
class="w-48"
@create="onCreate"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
function onCreate(item: string) {
items.value.push(item)
value.value = item
}
</script>
<template>
<UInputMenu
v-model="value"
create-item
:items="items"
class="w-48"
@create="onCreate"
/>
</template>
always, um sie auch dann anzuzeigen, wenn ähnliche Werte vorhanden sind.@create, um die Erstellung des Elements zu behandeln. Sie erhalten das Ereignis und das Element als Argumente.Mit hergeholten Elementen
Sie können Elemente aus einer API abrufen und im InputMenu verwenden.
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
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
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
:items="users"
:loading="status === 'pending'"
icon="i-lucide-user"
placeholder="Select user"
@update:open="onOpen"
>
<template #leading="{ modelValue, ui }">
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:class="ui.leadingAvatar()"
/>
</template>
</UInputMenu>
</template>
useLazyFetch mit immediate: false verwendet, um Daten nur beim Öffnen des Menüs abzurufen, wodurch unnötige API-Aufrufe beim Laden der Seite vermieden werden.With Ignore Filter (Deutsche Ausgabe)
Setzen Sie die ignore-filter prop auf true, um die interne Suche zu deaktivieren und Ihre eigene Suchlogik zu verwenden.
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'input-menu-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
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
v-model:search-term="searchTerm"
:items="users"
:loading="status === 'pending'"
ignore-filter
icon="i-lucide-user"
placeholder="Select user"
@update:open="onOpen"
>
<template #leading="{ modelValue, ui }">
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:class="ui.leadingAvatar()"
/>
</template>
</UInputMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'input-menu-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
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
v-model:search-term="searchTerm"
:items="users"
:loading="status === 'pending'"
ignore-filter
icon="i-lucide-user"
placeholder="Select user"
@update:open="onOpen"
>
<template #leading="{ modelValue, ui }">
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:class="ui.leadingAvatar()"
/>
</template>
</UInputMenu>
</template>
refDebounced verwendet, um die API-Aufrufe zu entkräften. Der Abruf wird mit immediate: false verschoben, sodass keine Anforderung gestellt wird, bis das Menü geöffnet wird.With Filterfelder
Verwenden Sie die filter-fields-Prop mit einem Array von Feldern, um nach. Defaults auf [labelKey] zu filtern.
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
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
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
:items="users"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
icon="i-lucide-user"
placeholder="Select user"
class="w-80"
@update:open="onOpen"
>
<template #leading="{ modelValue, ui }">
<UAvatar
v-if="modelValue"
v-bind="modelValue.avatar"
:size="(ui.leadingAvatarSize() as AvatarProps['size'])"
:class="ui.leadingAvatar()"
/>
</template>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</UInputMenu>
</template>
useLazyFetch mit immediate: false verwendet, um Daten nur beim Öffnen des Menüs abzurufen, wodurch unnötige API-Aufrufe beim Laden der Seite vermieden werden.Virtualisierung: badge{label="4.1+" class="align-text-top"}
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 { InputMenuItem } from '@nuxt/ui'
const items: InputMenuItem[] = Array(1000)
.fill(0)
.map((_, i) => ({
label: `item-${i}`,
value: i
}))
</script>
<template>
<UInputMenu virtualize :items="items" class="w-48" />
</template>With infinite scroll: badge{label="4.4+" class="align-text-top"} (Für Deutschland)
Sie können das Composable useInfiniteScroll verwenden, um mehr Daten zu laden, während der Benutzer scrollt.
<script setup lang="ts">
import { useInfiniteScroll } from '@vueuse/core'
type User = {
firstName: string
}
type UserResponse = {
users: User[]
total: number
skip: number
limit: number
}
const skip = ref(0)
const { data, status, execute } = await useLazyFetch(
'https://dummyjson.com/users?limit=10&select=firstName',
{
key: 'input-menu-users-infinite-scroll',
params: { skip },
transform: (data?: UserResponse) => {
return data?.users.map((user) => user.firstName)
},
immediate: false
}
)
const users = ref<string[]>([])
watch(data, () => {
users.value = [...users.value, ...(data.value || [])]
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
const inputMenu = useTemplateRef('inputMenu')
onMounted(() => {
useInfiniteScroll(
() => inputMenu.value?.viewportRef,
() => {
skip.value += 10
},
{
canLoadMore: () => {
return status.value !== 'pending'
}
}
)
})
</script>
<template>
<UInputMenu ref="inputMenu" placeholder="Select user" :items="users" @update:open="onOpen" />
</template><script setup lang="ts">
import { ref, watch, onMounted, useTemplateRef } from 'vue'
import { useInfiniteScroll } from '@vueuse/core'
type User = {
firstName: string
}
type UserResponse = {
users: User[]
total: number
skip: number
limit: number
}
const skip = ref(0)
const { data, status, execute } = await useLazyFetch(
'https://dummyjson.com/users?limit=10&select=firstName',
{
key: 'input-menu-users-infinite-scroll',
params: { skip },
transform: (data?: UserResponse) => {
return data?.users.map((user) => user.firstName)
},
immediate: false
}
)
const users = ref<string[]>([])
watch(data, () => {
users.value = [...users.value, ...(data.value || [])]
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
const inputMenu = useTemplateRef('inputMenu')
onMounted(() => {
useInfiniteScroll(
() => inputMenu.value?.viewportRef,
() => {
skip.value += 10
},
{
canLoadMore: () => {
return status.value !== 'pending'
}
}
)
})
</script>
<template>
<UInputMenu ref="inputMenu" placeholder="Select user" :items="users" @update:open="onOpen" />
</template>useLazyFetch mit immediate: false verwendet, sodass Daten nur beim Scrollen des Benutzers geladen werden.Mit voller Inhaltsbreite.
Sie können den Inhalt auf die volle Breite seiner Elemente erweitern, indem Sie die min-w-fit-Klasse auf dem ui.content-Steckplatz hinzufügen.
<script setup lang="ts">
const { data: users, 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
})
function onOpen() {
if (!users.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
:items="users"
icon="i-lucide-user"
placeholder="Select user"
:ui="{ content: 'min-w-fit' }"
@update:open="onOpen"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</UInputMenu>
</template>
app.config.ts ändern:export default defineAppConfig({
ui: {
inputMenu: {
slots: {
content: 'min-w-fit'
}
}
}
})
Als Länderauswahl
Sie können das InputMenu als Länderauswahl mit Lazy Loading verwenden. Länder werden nur beim ersten Öffnen des Menüs abgerufen.
<script setup lang="ts">
const { data: countries, status, execute } = await useLazyFetch<{
name: string
code: string
emoji: string
}[]>('/api/countries.json', {
key: 'api-countries',
immediate: false
})
function onOpen() {
if (!countries.value?.length) {
execute()
}
}
</script>
<template>
<UInputMenu
:items="countries"
:loading="status === 'pending'"
label-key="name"
:search-input="{ icon: 'i-lucide-search' }"
placeholder="Select country"
class="w-48"
@update:open="onOpen"
>
<template #leading="{ modelValue, ui }">
<span v-if="modelValue" class="size-5 text-center">
{{ modelValue?.emoji }}
</span>
<UIcon v-else name="i-lucide-earth" :class="ui.leadingIcon()" />
</template>
<template #item-leading="{ item }">
<span class="size-5 text-center">
{{ item.emoji }}
</span>
</template>
</UInputMenu>
</template>
useLazyFetch mit immediate: false verwendet, um nur Länder zu laden, wenn das Menü zum ersten Mal geöffnet wird.API ist
Props Bearbeiten
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
id | string | |
type | 'text' | "number" | "search" | "color" | "button" | "checkbox" | "date" | "datetime-local" | "email" | "file" | "hidden" | "image" | "month" | "password" | "radio" | "range" | "reset" | "submit" | "tel" | "text" | "time" | "url" | "week" | string |
placeholder | stringThe placeholder text when the input is empty. | |
color | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
variant | 'outline' | "soft" | "outline" | "subtle" | "ghost" | "none" |
size | 'md' | "sm" | "md" | "xs" | "lg" | "xl" |
required | boolean | |
autofocus | boolean | |
autofocusDelay | 0 | number |
trailingIcon | appConfig.ui.icons.chevronDown | anyThe icon displayed to open the menu. |
selectedIcon | appConfig.ui.icons.check | anyThe icon displayed when an item is selected. |
deleteIcon | appConfig.ui.icons.close | anyThe icon displayed to delete a tag.
Works only when |
clear | false | C & false | C & true | C & Partial<Omit<ButtonProps, LinkPropsKeys>>Display a clear button to reset the model value. Can be an object to pass additional props to the Button. |
clearIcon | appConfig.ui.icons.close | anyThe icon displayed in the clear button. |
content | { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' } | ComboboxContentProps & Partial<EmitsToProps<DismissableLayerEmits>>The content of the menu. |
arrow | false | boolean | ComboboxArrowProps Display an arrow alongside the menu.
|
portal | true | string | false | true | HTMLElementRender the menu in a portal. |
virtualize | false | boolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefinedEnable virtualization for large lists. Note: when enabled, all groups are flattened into a single list due to a limitation of Reka UI (https://github.com/unovue/reka-ui/issues/1885). |
valueKey | undefined | VKWhen |
labelKey | 'label' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>When |
descriptionKey | 'description' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>When |
items | T | |
defaultValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>The value of the InputMenu when initially rendered. Use when you do not need to control the state of the InputMenu. | |
modelValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>The controlled value of the InputMenu. Can be binded-with with | |
modelModifiers | Mod | |
multiple | MWhether multiple options can be selected or not. | |
highlight | boolean Highlight the ring color like a focus state. | |
fixed | boolean Keep the mobile text size on all breakpoints. | |
mode | 'combobox' | "autocomplete" | "combobox"The behavior of the InputMenu.
|
createItem | false | boolean | "always" | { position?: "bottom" | "top" ; when?: "empty" | "always" | undefined; } | undefinedDetermines if custom user input that does not exist in options can be added. |
filterFields | [labelKey] | string[]Fields to filter items by. |
ignoreFilter | false | boolean When |
disabled | boolean When | |
open | boolean The controlled open state of the Combobox. Can be binded with | |
defaultOpen | boolean The open state of the combobox when it is initially rendered. | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
resetSearchTermOnBlur | true | boolean Whether to reset the searchTerm when the Combobox input blurred |
resetSearchTermOnSelect | true | boolean Whether to reset the searchTerm when the Combobox value is selected |
resetModelValueOnClear | true | boolean When |
highlightOnHover | boolean When | |
openOnClick | `false` | boolean Whether to open the combobox when the input is clicked |
openOnFocus | `false` | boolean Whether to open the combobox when the input is focused |
by | string | (a: T, b: T): booleanUse this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | |
icon | anyDisplay an icon based on the | |
avatar | AvatarPropsDisplay an avatar on the left side. | |
leading | boolean When | |
leadingIcon | anyDisplay an icon on the left side. | |
trailing | boolean When | |
loading | boolean When | |
loadingIcon | appConfig.ui.icons.loading | anyThe icon when the |
list | string | |
readonly | false | true | "true" | "false" | |
autocomplete | string | "on" | "off" | |
searchTerm | '' | string |
ui | { root?: SlotClass; base?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; leadingAvatar?: SlotClass; leadingAvatarSize?: SlotClass; trailing?: SlotClass; trailingIcon?: SlotClass; trailingClear?: SlotClass; arrow?: SlotClass; content?: SlotClass; viewport?: SlotClass; group?: SlotClass; empty?: SlotClass; label?: SlotClass; separator?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemLeadingChip?: SlotClass; itemLeadingChipSize?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemDescription?: SlotClass; tagsItem?: SlotClass; tagsItemText?: SlotClass; tagsItemDelete?: SlotClass; tagsItemDeleteIcon?: SlotClass; tagsInput?: SlotClass; } |
Slots (englisch)
| Slot | Type |
|---|---|
leading | { modelValue: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>; open: boolean; ui: object; } |
trailing | { modelValue: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>; open: boolean; ui: object; } |
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; } |
tags-item-text | { item: NestedItem<T>; index: number; } |
tags-item-delete | { item: NestedItem<T>; index: number; ui: object; } |
content-top | {} |
content-bottom | {} |
create-item-label | { item: string; } |
Emits (englisch)
| Event | Type |
|---|---|
update:open | [value: boolean] |
change | [event: Event] |
blur | [event: FocusEvent] |
focus | [event: FocusEvent] |
create | [item: string] |
clear | [] |
highlight | [payload: { ref: HTMLElement; value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>; } | undefined] |
remove-tag | [item: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>] |
update:modelValue | [value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>] |
update:searchTerm | [value: string] |
Expose (englisch)
Beim Zugriff auf die Komponente über eine Template-Referenz können Sie Folgendes verwenden:
| Vorname | Typen |
|---|---|
inputRef Übersetzung | Ref<HTMLInputElement | null> nicht |
viewportRef nicht | Ref<HTMLDivElement | null> nicht |
Theme (englisch)
export default defineAppConfig({
ui: {
inputMenu: {
slots: {
root: 'relative inline-flex items-center',
base: [
'rounded-md',
'transition-colors'
],
leading: 'absolute inset-y-0 start-0 flex items-center',
leadingIcon: 'shrink-0 text-dimmed',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
trailing: 'group absolute inset-y-0 end-0 flex items-center disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none',
trailingIcon: 'shrink-0 text-dimmed',
trailingClear: 'p-0',
arrow: 'fill-bg stroke-default',
content: 'max-h-[min(15rem,var(--reka-combobox-content-available-height,15rem))] w-(--reka-combobox-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-combobox-content-transform-origin) pointer-events-auto flex flex-col',
viewport: 'relative scroll-py-1 overflow-y-auto flex-1',
group: 'p-1 isolate',
empty: 'text-center text-muted',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
item: [
'group relative w-full flex items-start gap-1.5 p-1.5 text-sm 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: '',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
tagsItem: 'px-1.5 py-0.5 rounded-sm font-medium inline-flex items-center gap-0.5 ring ring-inset ring-accented bg-elevated text-default data-disabled:cursor-not-allowed data-disabled:opacity-75',
tagsItemText: 'truncate',
tagsItemDelete: [
'inline-flex items-center rounded-xs text-dimmed hover:text-default hover:bg-accented/75 disabled:pointer-events-none',
'transition-colors'
],
tagsItemDeleteIcon: 'shrink-0',
tagsInput: 'flex-1 border-0 bg-transparent placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75'
},
variants: {
fieldGroup: {
horizontal: {
root: 'group has-focus-visible:z-[1]'
},
vertical: {
root: 'group has-focus-visible:z-[1]'
}
},
size: {
xs: {
base: 'px-2 py-1 text-sm/4 gap-1',
leading: 'ps-2',
trailing: 'pe-2',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4',
label: 'p-1 text-[10px]/3 gap-1',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4',
tagsItem: 'text-[10px]/3',
tagsItemDeleteIcon: 'size-3',
empty: 'p-2 text-xs'
},
sm: {
base: 'px-2.5 py-1.5 text-sm/4 gap-1.5',
leading: 'ps-2.5',
trailing: 'pe-2.5',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4',
label: 'p-1.5 text-[10px]/3 gap-1.5',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4',
tagsItem: 'text-[10px]/3',
tagsItemDeleteIcon: 'size-3',
empty: 'p-2.5 text-xs'
},
md: {
base: 'px-2.5 py-1.5 text-base/5 gap-1.5',
leading: 'ps-2.5',
trailing: 'pe-2.5',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs',
trailingIcon: 'size-5',
label: 'p-1.5 text-xs gap-1.5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5',
tagsItem: 'text-xs',
tagsItemDeleteIcon: 'size-3.5',
empty: 'p-2.5 text-sm'
},
lg: {
base: 'px-3 py-2 text-base/5 gap-2',
leading: 'ps-3',
trailing: 'pe-3',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs',
trailingIcon: 'size-5',
label: 'p-2 text-xs gap-2',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5',
tagsItem: 'text-xs',
tagsItemDeleteIcon: 'size-3.5',
empty: 'p-3 text-sm'
},
xl: {
base: 'px-3 py-2 text-base gap-2',
leading: 'ps-3',
trailing: 'pe-3',
leadingIcon: 'size-6',
leadingAvatarSize: 'xs',
trailingIcon: 'size-6',
label: 'p-2 text-sm gap-2',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
tagsItem: 'text-sm',
tagsItemDeleteIcon: 'size-4',
empty: 'p-3 text-base'
}
},
variant: {
outline: 'text-highlighted bg-default ring ring-inset ring-accented',
soft: 'text-highlighted bg-elevated/50 hover:bg-elevated focus:bg-elevated disabled:bg-elevated/50',
subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
none: 'text-highlighted bg-transparent focus:outline-none'
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
leading: {
true: ''
},
trailing: {
true: ''
},
loading: {
true: ''
},
highlight: {
true: ''
},
fixed: {
false: ''
},
type: {
file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
},
virtualize: {
true: {
viewport: 'p-1 isolate'
},
false: {
viewport: 'divide-y divide-default'
}
},
multiple: {
true: {
root: 'flex-wrap'
},
false: {
base: 'w-full border-0 placeholder:text-dimmed disabled:cursor-not-allowed disabled:opacity-75'
}
}
},
compoundVariants: [
{
multiple: false,
fieldGroup: 'horizontal',
class: {
base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
}
},
{
multiple: false,
fieldGroup: 'vertical',
class: {
base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
}
},
{
multiple: true,
fieldGroup: 'horizontal',
class: {
base: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]'
}
},
{
multiple: true,
fieldGroup: 'vertical',
class: {
base: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
}
},
{
variant: 'soft',
multiple: true,
class: 'has-focus:bg-elevated has-focus-visible:outline-3'
},
{
variant: 'ghost',
multiple: true,
class: 'has-focus:bg-elevated has-focus-visible:outline-3'
},
{
color: 'primary',
multiple: true,
variant: [
'outline',
'subtle'
],
class: 'has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
{
color: 'neutral',
multiple: true,
variant: [
'outline',
'subtle'
],
class: 'has-focus-visible:outline-3 has-focus-visible:ring-inverted'
},
{
color: 'primary',
variant: [
'outline',
'subtle'
],
class: 'outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
},
{
color: 'primary',
variant: [
'soft',
'ghost'
],
class: 'outline-primary/25 focus-visible:outline-3'
},
{
color: 'primary',
highlight: true,
class: 'ring ring-inset ring-primary'
},
{
color: 'neutral',
variant: [
'outline',
'subtle'
],
class: 'outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
},
{
color: 'neutral',
variant: [
'soft',
'ghost'
],
class: 'outline-inverted/25 focus-visible:outline-3'
},
{
color: 'neutral',
highlight: true,
class: 'ring ring-inset ring-inverted'
},
{
leading: true,
size: 'xs',
class: 'ps-7'
},
{
leading: true,
size: 'sm',
class: 'ps-8'
},
{
leading: true,
size: 'md',
class: 'ps-9'
},
{
leading: true,
size: 'lg',
class: 'ps-10'
},
{
leading: true,
size: 'xl',
class: 'ps-11'
},
{
trailing: true,
size: 'xs',
class: 'pe-7'
},
{
trailing: true,
size: 'sm',
class: 'pe-8'
},
{
trailing: true,
size: 'md',
class: 'pe-9'
},
{
trailing: true,
size: 'lg',
class: 'pe-10'
},
{
trailing: true,
size: 'xl',
class: 'pe-11'
},
{
loading: true,
leading: true,
class: {
leadingIcon: 'animate-spin'
}
},
{
loading: true,
leading: false,
trailing: true,
class: {
trailingIcon: 'animate-spin'
}
},
{
fixed: false,
size: 'xs',
class: 'md:text-xs'
},
{
fixed: false,
size: 'sm',
class: 'md:text-xs'
},
{
fixed: false,
size: 'md',
class: 'md:text-sm'
},
{
fixed: false,
size: 'lg',
class: 'md:text-sm'
}
],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
inputMenu: {
slots: {
root: 'relative inline-flex items-center',
base: [
'rounded-md',
'transition-colors'
],
leading: 'absolute inset-y-0 start-0 flex items-center',
leadingIcon: 'shrink-0 text-dimmed',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
trailing: 'group absolute inset-y-0 end-0 flex items-center disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none',
trailingIcon: 'shrink-0 text-dimmed',
trailingClear: 'p-0',
arrow: 'fill-bg stroke-default',
content: 'max-h-[min(15rem,var(--reka-combobox-content-available-height,15rem))] w-(--reka-combobox-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-combobox-content-transform-origin) pointer-events-auto flex flex-col',
viewport: 'relative scroll-py-1 overflow-y-auto flex-1',
group: 'p-1 isolate',
empty: 'text-center text-muted',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
item: [
'group relative w-full flex items-start gap-1.5 p-1.5 text-sm 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: '',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
tagsItem: 'px-1.5 py-0.5 rounded-sm font-medium inline-flex items-center gap-0.5 ring ring-inset ring-accented bg-elevated text-default data-disabled:cursor-not-allowed data-disabled:opacity-75',
tagsItemText: 'truncate',
tagsItemDelete: [
'inline-flex items-center rounded-xs text-dimmed hover:text-default hover:bg-accented/75 disabled:pointer-events-none',
'transition-colors'
],
tagsItemDeleteIcon: 'shrink-0',
tagsInput: 'flex-1 border-0 bg-transparent placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75'
},
variants: {
fieldGroup: {
horizontal: {
root: 'group has-focus-visible:z-[1]'
},
vertical: {
root: 'group has-focus-visible:z-[1]'
}
},
size: {
xs: {
base: 'px-2 py-1 text-sm/4 gap-1',
leading: 'ps-2',
trailing: 'pe-2',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4',
label: 'p-1 text-[10px]/3 gap-1',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4',
tagsItem: 'text-[10px]/3',
tagsItemDeleteIcon: 'size-3',
empty: 'p-2 text-xs'
},
sm: {
base: 'px-2.5 py-1.5 text-sm/4 gap-1.5',
leading: 'ps-2.5',
trailing: 'pe-2.5',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4',
label: 'p-1.5 text-[10px]/3 gap-1.5',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4',
tagsItem: 'text-[10px]/3',
tagsItemDeleteIcon: 'size-3',
empty: 'p-2.5 text-xs'
},
md: {
base: 'px-2.5 py-1.5 text-base/5 gap-1.5',
leading: 'ps-2.5',
trailing: 'pe-2.5',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs',
trailingIcon: 'size-5',
label: 'p-1.5 text-xs gap-1.5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5',
tagsItem: 'text-xs',
tagsItemDeleteIcon: 'size-3.5',
empty: 'p-2.5 text-sm'
},
lg: {
base: 'px-3 py-2 text-base/5 gap-2',
leading: 'ps-3',
trailing: 'pe-3',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs',
trailingIcon: 'size-5',
label: 'p-2 text-xs gap-2',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5',
tagsItem: 'text-xs',
tagsItemDeleteIcon: 'size-3.5',
empty: 'p-3 text-sm'
},
xl: {
base: 'px-3 py-2 text-base gap-2',
leading: 'ps-3',
trailing: 'pe-3',
leadingIcon: 'size-6',
leadingAvatarSize: 'xs',
trailingIcon: 'size-6',
label: 'p-2 text-sm gap-2',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
tagsItem: 'text-sm',
tagsItemDeleteIcon: 'size-4',
empty: 'p-3 text-base'
}
},
variant: {
outline: 'text-highlighted bg-default ring ring-inset ring-accented',
soft: 'text-highlighted bg-elevated/50 hover:bg-elevated focus:bg-elevated disabled:bg-elevated/50',
subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
none: 'text-highlighted bg-transparent focus:outline-none'
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
leading: {
true: ''
},
trailing: {
true: ''
},
loading: {
true: ''
},
highlight: {
true: ''
},
fixed: {
false: ''
},
type: {
file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
},
virtualize: {
true: {
viewport: 'p-1 isolate'
},
false: {
viewport: 'divide-y divide-default'
}
},
multiple: {
true: {
root: 'flex-wrap'
},
false: {
base: 'w-full border-0 placeholder:text-dimmed disabled:cursor-not-allowed disabled:opacity-75'
}
}
},
compoundVariants: [
{
multiple: false,
fieldGroup: 'horizontal',
class: {
base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
}
},
{
multiple: false,
fieldGroup: 'vertical',
class: {
base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
}
},
{
multiple: true,
fieldGroup: 'horizontal',
class: {
base: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]'
}
},
{
multiple: true,
fieldGroup: 'vertical',
class: {
base: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
}
},
{
variant: 'soft',
multiple: true,
class: 'has-focus:bg-elevated has-focus-visible:outline-3'
},
{
variant: 'ghost',
multiple: true,
class: 'has-focus:bg-elevated has-focus-visible:outline-3'
},
{
color: 'primary',
multiple: true,
variant: [
'outline',
'subtle'
],
class: 'has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
{
color: 'neutral',
multiple: true,
variant: [
'outline',
'subtle'
],
class: 'has-focus-visible:outline-3 has-focus-visible:ring-inverted'
},
{
color: 'primary',
variant: [
'outline',
'subtle'
],
class: 'outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
},
{
color: 'primary',
variant: [
'soft',
'ghost'
],
class: 'outline-primary/25 focus-visible:outline-3'
},
{
color: 'primary',
highlight: true,
class: 'ring ring-inset ring-primary'
},
{
color: 'neutral',
variant: [
'outline',
'subtle'
],
class: 'outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
},
{
color: 'neutral',
variant: [
'soft',
'ghost'
],
class: 'outline-inverted/25 focus-visible:outline-3'
},
{
color: 'neutral',
highlight: true,
class: 'ring ring-inset ring-inverted'
},
{
leading: true,
size: 'xs',
class: 'ps-7'
},
{
leading: true,
size: 'sm',
class: 'ps-8'
},
{
leading: true,
size: 'md',
class: 'ps-9'
},
{
leading: true,
size: 'lg',
class: 'ps-10'
},
{
leading: true,
size: 'xl',
class: 'ps-11'
},
{
trailing: true,
size: 'xs',
class: 'pe-7'
},
{
trailing: true,
size: 'sm',
class: 'pe-8'
},
{
trailing: true,
size: 'md',
class: 'pe-9'
},
{
trailing: true,
size: 'lg',
class: 'pe-10'
},
{
trailing: true,
size: 'xl',
class: 'pe-11'
},
{
loading: true,
leading: true,
class: {
leadingIcon: 'animate-spin'
}
},
{
loading: true,
leading: false,
trailing: true,
class: {
trailingIcon: 'animate-spin'
}
},
{
fixed: false,
size: 'xs',
class: 'md:text-xs'
},
{
fixed: false,
size: 'sm',
class: 'md:text-xs'
},
{
fixed: false,
size: 'md',
class: 'md:text-sm'
},
{
fixed: false,
size: 'lg',
class: 'md:text-sm'
}
],
defaultVariants: {
size: 'md',
color: 'primary',
variant: 'outline'
}
}
}
})
]
})