SelectMenu

组合框GitHub
一个高级可搜索的选择元素。

用法

使用 v-model 指令控制 SelectMenu 的值,或者在不需要控制其状态时使用 default-value prop 设置初始值。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" :items="items" />
</template>
使用此组件替代 Select,以利用 Reka UI 的组合框提供搜索功能和多选功能的组件。
此组件与 InputMenu 类似,但它使用的是 Select 而不是带有菜单内搜索功能的 Input。

items prop 用作字符串、数字或布尔值的数组

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" :items="items" class="w-48" />
</template>

您还可以传入一个包含以下属性的对象数组

  • label?: string
  • type?: "label" | "separator" | "item"
  • icon?: string
  • avatar?: AvatarProps
  • chip?: ChipProps
  • disabled?: boolean
  • onSelect?: (e: Event) => void
  • class?: any
  • ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }
<script setup lang="ts">
import type { SelectMenuItem } from '@nuxt/ui'

const items = ref<SelectMenuItem[]>([
  {
    label: 'Backlog'
  },
  {
    label: 'Todo'
  },
  {
    label: 'In Progress'
  },
  {
    label: 'Done'
  }
])
const value = ref({
  label: 'Todo'
})
</script>

<template>
  <USelectMenu v-model="value" :items="items" class="w-48" />
</template>
Select 组件不同,SelectMenu 默认需要将整个对象传递给 v-model 指令或 default-value prop。

您还可以将数组的数组传递给 items prop,以显示分组的项。

<script setup lang="ts">
const items = ref([
  ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple'],
  ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
])
const value = ref('Apple')
</script>

<template>
  <USelectMenu v-model="value" :items="items" class="w-48" />
</template>

值键

您可以使用 value-key prop 绑定对象的单个属性,而不是整个对象。默认为 undefined

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

const items = ref<SelectMenuItem[]>([
  {
    label: 'Backlog',
    id: 'backlog'
  },
  {
    label: 'Todo',
    id: 'todo'
  },
  {
    label: 'In Progress',
    id: 'in_progress'
  },
  {
    label: 'Done',
    id: 'done'
  }
])
const value = ref('todo')
</script>

<template>
  <USelectMenu v-model="value" value-key="id" :items="items" class="w-48" />
</template>
model-value 是一个对象时,使用 by 属性按字段而不是引用来比较对象。

多选

使用 multiple prop 允许多选,选定的项目将在触发器中用逗号分隔。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref(['Backlog', 'Todo'])
</script>

<template>
  <USelectMenu v-model="value" multiple :items="items" class="w-48" />
</template>
请确保将数组传递给 default-value 属性或 v-model 指令。

占位符

使用 placeholder 属性设置占位文本。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>

<template>
  <USelectMenu placeholder="Select status" :items="items" class="w-48" />
</template>

搜索输入

使用 search-input prop 可以自定义或隐藏搜索输入(使用 false 值)。

您可以传递 Input 组件的任何属性来定制它。

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

const items = ref<SelectMenuItem[]>([
  {
    label: 'Backlog',
    icon: 'i-lucide-circle-help'
  },
  {
    label: 'Todo',
    icon: 'i-lucide-circle-plus'
  },
  {
    label: 'In Progress',
    icon: 'i-lucide-circle-arrow-up'
  },
  {
    label: 'Done',
    icon: 'i-lucide-circle-check'
  }
])
const value = ref({
  label: 'Backlog',
  icon: 'i-lucide-circle-help'
})
</script>

<template>
  <USelectMenu
    v-model="value"
    :search-input="{
      placeholder: 'Filter...',
      icon: 'i-lucide-search'
    }"
    :items="items"
    class="w-48"
  />
</template>
您可以将 search-input prop 设置为 false 来隐藏搜索输入。

内容

使用 content prop 控制 SelectMenu 内容的渲染方式,例如其 alignside

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu
    v-model="value"
    :content="{
      align: 'center',
      side: 'bottom',
      sideOffset: 8
    }"
    :items="items"
    class="w-48"
  />
</template>

箭头

使用 arrow prop 在 SelectMenu 上显示一个箭头。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" arrow :items="items" class="w-48" />
</template>

颜色

使用 color prop 更改 SelectMenu 获得焦点时的环形颜色。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" color="neutral" highlight :items="items" class="w-48" />
</template>
highlight 属性在此用于显示焦点状态。当发生验证错误时,它会在内部使用。

变体

使用 variant prop 更改 SelectMenu 的变体。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" color="neutral" variant="subtle" :items="items" class="w-48" />
</template>

尺寸

使用 size prop 更改 SelectMenu 的大小。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" size="xl" :items="items" class="w-48" />
</template>

Icon

使用 icon prop 在 SelectMenu 内部显示一个 Icon

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" icon="i-lucide-search" size="md" :items="items" class="w-48" />
</template>

尾部图标

使用 trailing-icon 属性来自定义尾部 Icon。默认为 i-lucide-chevron-down

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu
    v-model="value"
    trailing-icon="i-lucide-arrow-down"
    size="md"
    :items="items"
    class="w-48"
  />
</template>
您可以在 app.config.ts 中通过 ui.icons.chevronDown 键全局自定义此图标。
您可以在 vite.config.ts 中通过 ui.icons.chevronDown 键全局自定义此图标。

选中图标

使用 selected-icon 属性来自定义选中项目时的图标。默认为 i-lucide-check

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu
    v-model="value"
    selected-icon="i-lucide-flame"
    size="md"
    :items="items"
    class="w-48"
  />
</template>
您可以在 app.config.ts 文件中,通过 ui.icons.check 键来全局自定义此图标。
您可以在 vite.config.ts 文件中,通过 ui.icons.check 键来全局自定义此图标。

清除 4.4+

当选中一个值时,使用 clear prop 显示清除按钮。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" clear :items="items" class="w-48" />
</template>

清除图标 4.4+

使用 clear-icon prop 自定义清除按钮 Icon。默认为 i-lucide-x

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" clear clear-icon="i-lucide-trash" :items="items" class="w-48" />
</template>
你可以在 app.config.ts 中的 ui.icons.close 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.close 键下全局自定义此图标。

Avatar

使用 avatar prop 在 SelectMenu 内部显示一个 Avatar

<script setup lang="ts">
const items = ref(['Nuxt', 'NuxtHub', 'NuxtLabs', 'Nuxt Modules', 'Nuxt Community'])
const value = ref('Nuxt')
</script>

<template>
  <USelectMenu
    v-model="value"
    :avatar="{
      src: 'https://github.com/nuxt.png'
    }"
    :items="items"
    class="w-48"
  />
</template>

加载中

使用 loading prop 在 SelectMenu 上显示加载图标。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" loading :items="items" class="w-48" />
</template>

加载图标

使用 loading-icon prop 来自定义加载图标。默认为 i-lucide-loader-circle

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" loading loading-icon="i-lucide-loader" :items="items" class="w-48" />
</template>
你可以在 app.config.ts 中的 ui.icons.loading 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.loading 键下全局自定义此图标。

禁用

使用 disabled prop 禁用 SelectMenu。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
</script>

<template>
  <USelectMenu disabled placeholder="Select status" :items="items" class="w-48" />
</template>

示例

使用项类型

您可以将 type 属性与 separator 一起使用,以在项目之间显示分隔符,或使用 label 来显示标签。

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

const items = ref<SelectMenuItem[]>([
  {
    type: 'label',
    label: 'Fruits'
  },
  'Apple',
  'Banana',
  'Blueberry',
  'Grapes',
  'Pineapple',
  {
    type: 'separator'
  },
  {
    type: 'label',
    label: 'Vegetables'
  },
  'Aubergine',
  'Broccoli',
  'Carrot',
  'Courgette',
  'Leek'
])
const value = ref('Apple')
</script>

<template>
  <USelectMenu v-model="value" :items="items" class="w-48" />
</template>

项中带图标

您可以使用 icon 属性在项目(items)中显示一个 Icon

<script setup lang="ts">
import type { SelectMenuItem } 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 SelectMenuItem[])

const value = ref(items.value[0])
</script>

<template>
  <USelectMenu v-model="value" :icon="value?.icon" :items="items" class="w-48" />
</template>
您还可以使用 #leading 插槽显示选中的图标。

项中带头像

您可以使用 avatar 属性在项目(items)中显示一个 Avatar

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

const items = ref([
  {
    label: 'benjamincanac',
    value: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png',
      alt: 'benjamincanac'
    }
  },
  {
    label: 'romhml',
    value: 'romhml',
    avatar: {
      src: 'https://github.com/romhml.png',
      alt: 'romhml'
    }
  },
  {
    label: 'noook',
    value: 'noook',
    avatar: {
      src: 'https://github.com/noook.png',
      alt: 'noook'
    }
  },
  {
    label: 'sandros94',
    value: 'sandros94',
    avatar: {
      src: 'https://github.com/sandros94.png',
      alt: 'sandros94'
    }
  }
] satisfies SelectMenuItem[])

const value = ref(items.value[0])
</script>

<template>
  <USelectMenu v-model="value" :avatar="value?.avatar" :items="items" class="w-48" />
</template>
您还可以使用 #leading 插槽显示选中的头像。

项中带标签

您可以使用 chip 属性在项目(items)中显示一个 Chip

<script setup lang="ts">
import type { SelectMenuItem, 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 SelectMenuItem[])

const value = ref(items.value[0])
</script>

<template>
  <USelectMenu v-model="value" :items="items" class="w-48">
    <template #leading="{ modelValue, ui }">
      <UChip
        v-if="modelValue"
        v-bind="modelValue.chip"
        inset
        standalone
        :size="(ui.itemLeadingChipSize() as ChipProps['size'])"
        :class="ui.itemLeadingChip()"
      />
    </template>
  </USelectMenu>
</template>
在此示例中,#leading 插槽用于显示选中的标签。

控制打开状态

您可以通过使用default-open prop 或v-model:open指令来控制打开状态。

<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>
  <USelectMenu v-model="value" v-model:open="open" :items="items" class="w-48" />
</template>
在此示例中,利用 defineShortcuts,您可以通过按 O 键来切换 SelectMenu。

控制搜索词

使用 v-model:search-term 指令控制搜索词。

<script setup lang="ts">
const searchTerm = ref('D')
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu v-model="value" v-model:search-term="searchTerm" :items="items" class="w-48" />
</template>

带旋转图标

这是一个带有旋转图标的示例,该图标指示 SelectMenu 的打开状态。

<script setup lang="ts">
const items = ref(['Backlog', 'Todo', 'In Progress', 'Done'])
const value = ref('Backlog')
</script>

<template>
  <USelectMenu
    v-model="value"
    :items="items"
    :ui="{
      trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200'
    }"
    class="w-48"
  />
</template>

使用创建项目

使用 create-item prop 允许用户添加未在预定义选项中的自定义值。

<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>
  <USelectMenu
    v-model="value"
    create-item
    :items="items"
    class="w-48"
    @create="onCreate"
  />
</template>
默认情况下,当未找到匹配项时,会显示创建选项。将其设置为 always,即使存在相似值也显示它。
使用 @create 事件处理项目的创建。您将收到事件和项目作为参数。

带获取的项

您可以从 API 获取项目并在 SelectMenu 中使用它们。

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

const { data: users, status } = await useFetch('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}` }
    }))
  },
  lazy: true
})
</script>

<template>
  <USelectMenu
    :items="users"
    :loading="status === 'pending'"
    icon="i-lucide-user"
    placeholder="Select user"
    class="w-48"
  >
    <template #leading="{ modelValue, ui }">
      <UAvatar
        v-if="modelValue"
        v-bind="modelValue.avatar"
        :size="(ui.leadingAvatarSize() as AvatarProps['size'])"
        :class="ui.leadingAvatar()"
      />
    </template>
  </USelectMenu>
</template>

带忽略过滤器

ignore-filter prop 设置为 true 以禁用内部搜索并使用您自己的搜索逻辑。

<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 } = await useFetch('https://jsonplaceholder.typicode.com/users', {
  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}` }
    }))
  },
  lazy: true
})
</script>

<template>
  <USelectMenu
    v-model:search-term="searchTerm"
    :items="users"
    :loading="status === 'pending'"
    ignore-filter
    icon="i-lucide-user"
    placeholder="Select user"
    class="w-48"
  >
    <template #leading="{ modelValue, ui }">
      <UAvatar
        v-if="modelValue"
        v-bind="modelValue.avatar"
        :size="(ui.leadingAvatarSize() as AvatarProps['size'])"
        :class="ui.leadingAvatar()"
      />
    </template>
  </USelectMenu>
</template>
此示例使用refDebounced来防抖 API 调用。

带筛选字段

使用 filter-fields prop 和一个字段数组进行筛选。默认为 [labelKey]

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

const { data: users, status } = await useFetch('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}` }
    }))
  },
  lazy: true
})
</script>

<template>
  <USelectMenu
    :items="users"
    :loading="status === 'pending'"
    :filter-fields="['label', 'email']"
    icon="i-lucide-user"
    placeholder="Select user"
    class="w-80"
  >
    <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>
  </USelectMenu>
</template>

使用虚拟化 4.1+

使用 virtualize 属性为大型列表启用虚拟化,可以是布尔值或对象(包含 { estimateSize: 32, overscan: 12 } 等选项)。

启用后,由于 Reka UI 的限制,所有组都会被展平为单个列表。
<script setup lang="ts">
import type { SelectMenuItem } from '@nuxt/ui'

const items: SelectMenuItem[] = Array(1000)
  .fill(0)
  .map((_, i) => ({
    label: `item-${i}`,
    value: i
  }))
</script>

<template>
  <USelectMenu virtualize :items="items" class="w-48" />
</template>

使用无限滚动 4.4+

您可以使用useInfiniteScroll组合函数,用于在用户滚动时加载更多数据。

<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 useFetch(
  'https://dummyjson.com/users?limit=10&select=firstName',
  {
    key: 'select-menu-users-infinite-scroll',
    params: { skip },
    transform: (data?: UserResponse) => {
      return data?.users.map((user) => user.firstName)
    },
    lazy: true,
    immediate: false
  }
)

const users = ref<string[]>([])

watch(data, () => {
  users.value = [...users.value, ...(data.value || [])]
})

execute()

const selectMenu = useTemplateRef('selectMenu')

onMounted(() => {
  useInfiniteScroll(
    () => selectMenu.value?.viewportRef,
    () => {
      skip.value += 10
    },
    {
      canLoadMore: () => {
        return status.value !== 'pending'
      }
    }
  )
})
</script>

<template>
  <USelectMenu ref="selectMenu" placeholder="Select user" :items="users" />
</template>

内容全宽

您可以通过在 ui.content 插槽上添加 min-w-fit 类来将内容扩展到其项目宽度的全屏。

<script setup lang="ts">
const { data: users } = await useFetch('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}` }
    }))
  },
  lazy: true
})
</script>

<template>
  <USelectMenu
    :items="users"
    icon="i-lucide-user"
    placeholder="Select user"
    :ui="{ content: 'min-w-fit' }"
    class="w-48"
  >
    <template #item-label="{ item }">
      {{ item.label }}

      <span class="text-muted">
        {{ item.email }}
      </span>
    </template>
  </USelectMenu>
</template>
您也可以在 app.config.ts 中全局更改内容宽度
export default defineAppConfig({
  ui: {
    selectMenu: {
      slots: {
        content: 'min-w-fit'
      }
    }
  }
})

作为国家选择器

此示例演示了如何将 SelectMenu 用作带有延迟加载功能的国家选择器——国家只在菜单打开时才被获取。

<script setup lang="ts">
const { data: countries, status, execute } = await useLazyFetch<{
  name: string
  code: string
  emoji: string
}[]>('/api/countries.json', {
  immediate: false
})

function onOpen() {
  if (!countries.value?.length) {
    execute()
  }
}
</script>

<template>
  <USelectMenu
    :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>
  </USelectMenu>
</template>

API

属性

属性默认值类型
idstring
placeholderstring

选择框为空时的占位符文本。

searchInputtrueboolean | InputProps<AcceptableValue, ModelModifiers>

是否显示搜索输入。可以是一个对象,用于向输入传递额外的属性。 { placeholder: '搜索...', variant: 'none' }

color'primary'"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"
variant'outline'"outline" | "soft" | "subtle" | "ghost" | "none"
尺寸'md'"sm" | "md" | "xs" | "lg" | "xl"
requiredboolean
trailingIconappConfig.ui.icons.chevronDownany

用于打开菜单的图标。

selectedIconappConfig.ui.icons.checkany

选中项时显示的图标。

清除falseC & false | C & true | C & Partial<Omit<ButtonProps, LinkPropsKeys>>

显示一个清除按钮来重置模型值。可以是对象,用于向 Button 传递其他属性。

clearIconappConfig.ui.icons.closeany

清除按钮中显示的图标。

内容{ side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }Omit<ComboboxContentProps, "asChild" | "as" | "forceMount"> & Partial<EmitsToProps<DismissableLayerEmits>>

菜单的内容。

arrowfalseboolean | Omit<ComboboxArrowProps, "asChild" | "as">

在菜单旁边显示一个箭头。

portaltruestring | false | true | HTMLElement

在 portal 中渲染菜单。

virtualizefalseboolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefined

为大型列表启用虚拟化。注意:启用后,由于 Reka UI 的限制 (https://github.com/unovue/reka-ui/issues/1885).

valueKeyundefinedVK

items 是一个对象数组时,选择要用作值的字段而不是对象本身。

labelKey'label'keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>

items 是对象数组时,选择用作标签的字段。

描述键'description'keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>

items 是一个对象数组时,选择要用作描述的字段。

itemsT
defaultValue_Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>

SelectMenu 初始渲染时的值。当您不需要控制 SelectMenu 的状态时使用。

modelValue_Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>

SelectMenu 的受控值。可以通过 v-model 绑定。

modelModifiersMod
multipleM

是否可以选择多个选项。

高亮boolean

高亮环形颜色,如同焦点状态。

createItemfalseboolean | "always" | { position?: "top" | "bottom" ; when?: "always" | "empty" | undefined; } | undefined

确定是否可以添加选项中不存在的自定义用户输入。

filterFields[labelKey]string[]

用于过滤项目的字段。

ignoreFilterfalseboolean

true 时,禁用默认过滤器,这对于自定义过滤(useAsyncData, useFetch 等)很有用。

autofocusboolean
autofocusDelay0number
disabledboolean

当为 true 时,阻止用户与列表框交互

openboolean

Combobox 的受控打开状态。可以使用 v-model:open 进行绑定。

defaultOpenboolean

组合框初次渲染时的打开状态。
当您不需要控制其打开状态时使用。

namestring

字段的名称。作为名称/值对的一部分随其所属表单提交。

resetSearchTermOnBlurtrueboolean

当组合框输入失去焦点时是否重置搜索词

resetSearchTermOnSelecttrueboolean

当组合框值被选中时是否重置搜索词

resetModelValueOnCleartrueboolean

true 时,modelValue 将重置为 null(如果 multiple 则为 [])。

highlightOnHoverboolean

true 时,鼠标悬停在项目上会触发高亮显示。

bystring | (a: T, b: T): boolean

使用此属性按特定字段比较对象,或提供自己的比较函数以完全控制对象的比较方式。

图标any

根据 leadingtrailing 属性显示图标。

avatarAvatarProps

在左侧显示头像。

前置boolean

当为 true 时,图标将显示在左侧。

leadingIconany

在左侧显示图标。

尾部boolean

当为 true 时,图标将显示在右侧。

loadingboolean

当为 true 时,将显示加载图标。

loadingIconappConfig.ui.icons.loadingany

loading prop 为 true 时显示的图标。

搜索词''string
ui{ base?: ClassNameValue; leading?: ClassNameValue; leadingIcon?: ClassNameValue; leadingAvatar?: ClassNameValue; leadingAvatarSize?: ClassNameValue; trailing?: ClassNameValue; trailingIcon?: ClassNameValue; value?: ClassNameValue; placeholder?: ClassNameValue; arrow?: ClassNameValue; content?: ClassNameValue; viewport?: ClassNameValue; group?: ClassNameValue; empty?: ClassNameValue; label?: ClassNameValue; separator?: ClassNameValue; item?: ClassNameValue; itemLeadingIcon?: ClassNameValue; itemLeadingAvatar?: ClassNameValue; itemLeadingAvatarSize?: ClassNameValue; itemLeadingChip?: ClassNameValue; itemLeadingChipSize?: ClassNameValue; itemTrailing?: ClassNameValue; itemTrailingIcon?: ClassNameValue; itemWrapper?: ClassNameValue; itemLabel?: ClassNameValue; itemDescription?: ClassNameValue; input?: ClassNameValue; focusScope?: ClassNameValue; trailingClear?: ClassNameValue; }
此组件还支持所有原生 <button> HTML 属性。

插槽

插槽类型
前置{ modelValue?: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C> | undefined; open: boolean; ui: object; }
default{ modelValue?: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C> | undefined; open: boolean; ui: object; }
尾部{ modelValue?: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C> | undefined; open: boolean; ui: object; }
{ searchTerm?: string | undefined; }
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: NestedItem<T>; index: number; }
item-trailing{ item: NestedItem<T>; index: number; ui: object; }
content-top{}
content-bottom{}
create-item-label{ item: string; }

事件

事件类型
update:open[value: boolean]
change[事件: Event]
blur[事件: FocusEvent]
focus[事件: FocusEvent]
create[item: string]
清除[]
高亮[payload: { ref: HTMLElement; value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>; } | undefined]
update:modelValue[value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, ExcludeItem>, Mod>, Mod>, Mod> | IsClearUsed<M, C>]
update:searchTerm[value: string]

可访问属性

通过模板引用访问组件时,您可以使用以下内容:

名称类型
triggerRefRef<HTMLButtonElement | null>
viewportRefRef<HTMLDivElement | null>

主题

app.config.ts
export default defineAppConfig({
  ui: {
    selectMenu: {
      slots: {
        base: [
          'relative group rounded-md inline-flex items-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-75',
          'transition-colors'
        ],
        leading: 'absolute inset-y-0 start-0 flex items-center',
        leadingIcon: 'shrink-0 text-dimmed',
        leadingAvatar: 'shrink-0',
        leadingAvatarSize: '',
        trailing: 'absolute inset-y-0 end-0 flex items-center',
        trailingIcon: 'shrink-0 text-dimmed',
        value: 'truncate pointer-events-none',
        placeholder: 'truncate text-dimmed',
        arrow: 'fill-default',
        content: [
          'max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto flex flex-col',
          'origin-(--reka-combobox-content-transform-origin) w-(--reka-combobox-trigger-width)'
        ],
        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 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',
        input: 'border-b border-default',
        focusScope: 'flex flex-col min-h-0',
        trailingClear: 'p-0'
      },
      variants: {
        fieldGroup: {
          horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
          vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
        },
        size: {
          xs: {
            base: 'px-2 py-1 text-xs 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',
            empty: 'p-1 text-xs'
          },
          sm: {
            base: 'px-2.5 py-1.5 text-xs 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',
            empty: 'p-1.5 text-xs'
          },
          md: {
            base: 'px-2.5 py-1.5 text-sm 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',
            empty: 'p-1.5 text-sm'
          },
          lg: {
            base: 'px-3 py-2 text-sm 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',
            empty: 'p-2 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',
            empty: 'p-2 text-base'
          }
        },
        variant: {
          outline: 'text-highlighted bg-default ring ring-inset ring-accented hover:bg-elevated disabled:bg-default',
          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 hover:bg-accented/75 disabled:bg-elevated',
          ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
          none: 'text-highlighted bg-transparent'
        },
        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'
          }
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary'
        },
        {
          color: 'primary',
          highlight: true,
          class: 'ring ring-inset ring-primary'
        },
        {
          color: 'neutral',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-inverted'
        },
        {
          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'
      }
    }
  }
})
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: {
        selectMenu: {
          slots: {
            base: [
              'relative group rounded-md inline-flex items-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-75',
              'transition-colors'
            ],
            leading: 'absolute inset-y-0 start-0 flex items-center',
            leadingIcon: 'shrink-0 text-dimmed',
            leadingAvatar: 'shrink-0',
            leadingAvatarSize: '',
            trailing: 'absolute inset-y-0 end-0 flex items-center',
            trailingIcon: 'shrink-0 text-dimmed',
            value: 'truncate pointer-events-none',
            placeholder: 'truncate text-dimmed',
            arrow: 'fill-default',
            content: [
              'max-h-60 w-(--reka-select-trigger-width) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] origin-(--reka-select-content-transform-origin) pointer-events-auto flex flex-col',
              'origin-(--reka-combobox-content-transform-origin) w-(--reka-combobox-trigger-width)'
            ],
            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 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',
            input: 'border-b border-default',
            focusScope: 'flex flex-col min-h-0',
            trailingClear: 'p-0'
          },
          variants: {
            fieldGroup: {
              horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
              vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
            },
            size: {
              xs: {
                base: 'px-2 py-1 text-xs 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',
                empty: 'p-1 text-xs'
              },
              sm: {
                base: 'px-2.5 py-1.5 text-xs 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',
                empty: 'p-1.5 text-xs'
              },
              md: {
                base: 'px-2.5 py-1.5 text-sm 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',
                empty: 'p-1.5 text-sm'
              },
              lg: {
                base: 'px-3 py-2 text-sm 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',
                empty: 'p-2 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',
                empty: 'p-2 text-base'
              }
            },
            variant: {
              outline: 'text-highlighted bg-default ring ring-inset ring-accented hover:bg-elevated disabled:bg-default',
              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 hover:bg-accented/75 disabled:bg-elevated',
              ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
              none: 'text-highlighted bg-transparent'
            },
            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'
              }
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary'
            },
            {
              color: 'primary',
              highlight: true,
              class: 'ring ring-inset ring-primary'
            },
            {
              color: 'neutral',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-inverted'
            },
            {
              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'
          }
        }
      }
    })
  ]
})
为便于阅读,compoundVariants 中的某些颜色已省略。请在 GitHub 上查看源代码。

更新日志

v4.5.0
  • cd343— fix(components): 支持可空 (nullable) 和可选 (optional) 类型 (#6060)
  • 058c6— fix(InputMenu/SelectMenu): 按匹配相关性排序过滤后的项目
  • 22cf1— fix(InputMenu/Select/SelectMenu): 从模型值类型中排除装饰性项目 (#6044)
  • c9704— feat(Theme): 新组件 (#4387)
  • 1ec16— fix(InputMenu/InputNumber/SelectMenu): 将 size 代理到按钮
v4.4.0
  • 36cd5— feat(components): 添加 by 属性 (#5906)
  • f4a94— feat(InputMenu/Select/SelectMenu): 为无限滚动暴露 viewportRef (#5836)
  • d51b4— feat(CommandPalette/InputMenu/SelectMenu/Tree): 将虚拟列表的 estimateSize 处理为函数 (#5748)
  • ec6b8— feat(InputMenu/SelectMenu): 添加 clear prop (#5643)
v4.3.0
  • a92ee— feat(InputMenu/Select/SelectMenu): 添加 modelModifiers 属性 (#5559)
v4.2.0
  • 418c8— fix(InputMenu): 选择创建项目时阻止更改事件
  • 56ae8— fix(components): 根据项目描述计算虚拟列表的 estimateSize
  • dd81d— feat(components): 添加 data-slot 属性 (#5447)
  • fda3c— fix(components): 清理 HTML 属性扩展
  • 5b177— feat(components): 扩展原生 HTML 属性 (#5348)
  • fce2d— fix(components)!: 统一暴露的 refs (#5385)
v4.1.0
  • 70cf0— feat(components): 处理项目中的 description (#5193)
  • 63c0a— feat(components): 在使用的插槽属性中暴露 ui (#5207)
  • 63074— fix(InputMenu/SelectMenu): 丰富可重用模板项目 prop
  • 84f87— feat(Tree): 添加全局事件处理程序和复选框示例 (#5195)
  • c744d— feat(components): 实现虚拟化 (#5162)
v4.0.0
  • 788d2— fix(components): 标准化类型接口的命名 (#4990)
v3.3.4
  • 11a03— fix(components): labelKeyvalueKey 支持点符号类型 (#4933)
v3.3.3
  • 7133f— fix(components): 修复 update:model-value 事件的类型错误 (#4853)
  • 61b60— feat(Icon): 允许传递组件而非名称 (#4766)
v3.3.1
  • 55dbc— fix(Select/InputMenu): 处理 FormField 内部通过标签进行的聚焦 (#4696)
  • 34ca8— fix(InputMenu/Select/SelectMenu): 当未找到项目时添加显示值回退 (#4689)
  • a0963— feat(FieldGroup)!: 从 ButtonGroup 更名 (#4596)
  • 5cb65— feat: 导入 @nuxt/ui-pro 组件 (#4675)
v3.3.0
  • 4d423— fix(InputMenu/SelectMenu): 改进没有 valueKey 的显示值
  • 48870— fix(InputMenu/SelectMenu): 搜索中过滤空项目
  • c92f9— fix(InputMenu/SelectMenu): 仅过滤非空字段
v3.2.0
  • b0364— fix(SelectMenu): 动态输入大小
  • 7a2bd— feat(Select/SelectMenu/Tabs): 暴露触发器 refs
  • 1a4de— feat(Select/SelectMenu): 处理动态 autofocus
  • 483e4— fix(Select/SelectMenu): 多选时防止空字符串显示
  • 7df7e— fix(Select/SelectMenu): 显示虚假值
v3.1.3
  • f95ab— fix(InputMenu/Select/SelectMenu): 手动视口以显示滚动条
v3.1.2
  • b9adc— feat(components): 在 items 中添加 ui 字段 (#4060)
  • e6e51— fix(components): class 应优先于 ui 属性
v3.1.0
  • 1a463— feat(components): 添加新的 content-topcontent-bottom 插槽 (#3886)
  • 9ca21— fix(InputMenu/SelectMenu): 移除 valueKey 字符串情况
  • 29fa4— feat(App): 添加全局 portal 属性 (#3688)
  • d49e0— feat(module): 定义中性效用类 (neutral utilities) (#3629)
  • 01d8d— fix(components): 在 popper 内容中遵循 transform-origin (#3919)
  • 39c86— fix(components): 在 @nuxt/module-builder 升级后重构类型 (#3855)
  • 8435a— fix(InputMenu/SelectMenu): 防止选中已禁用的 ( disabled ) 项目
  • cea88— feat(InputMenu/SelectMenu): 处理 resetSearchTermOnSelect
  • 52a97— fix(InputMenu/SelectMenu): 支持任意 value (#3779)
  • f25fe— fix(InputMenu/SelectMenu): 正确调用 onSelect 事件 (#3735)
v3.0.2
  • 94b6e— fix(InputMenu/SelectMenu): 空搜索结果
  • b9983— fix(components): 优化泛型类型 (#3331)
v3.0.1
  • 5dec0— feat(components): 处理 content 属性中的事件