CommandPalette

一个命令面板,由 Fuse.js 提供支持的全文本搜索,实现高效模糊匹配。

用法

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

<script setup lang="ts">
const groups = ref([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png'
        }
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        avatar: {
          src: 'https://github.com/danielroe.png'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png'
        }
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        avatar: {
          src: 'https://github.com/genu.png'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1 h-80" />
</template>
您还可以使用 @update:model-value 事件来监听选中的项目。

分组

CommandPalette 组件会过滤分组,并根据用户输入的文本相关性对匹配的命令进行排名。它提供动态、即时的搜索结果,从而实现高效的命令发现。使用 groups 属性,它是一个具有以下属性的对象数组:

您必须为每个组提供一个 id,否则该组将被忽略。

每个组都包含一个 items 数组,其中包含定义命令的对象。每个项目可以具有以下属性:

  • prefix?: string
  • label?: string
  • suffix?: string
  • icon?: string
  • avatar?: AvatarProps
  • chip?: ChipProps
  • kbds?: string[] | KbdProps[]
  • active?: boolean
  • loading?: boolean
  • disabled?: boolean
  • slot?: string
  • placeholder?: string
  • children?: CommandPaletteItem[]
  • onSelect?: (e: Event) => void
  • class?: any
  • ui?: { item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelPrefix?: ClassNameValue, itemLabelBase?: ClassNameValue, itemLabelSuffix?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue, itemTrailingHighlightedIcon?: ClassNameValue, itemTrailingIcon?: ClassNameValue }

您可以传递 Link 组件的任何属性,例如 totarget 等。

<script setup lang="ts">
const groups = ref([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png'
        }
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        avatar: {
          src: 'https://github.com/danielroe.png'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png'
        }
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        avatar: {
          src: 'https://github.com/genu.png'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
每个项目都可以包含一个 children 数组,其中包含以下属性的对象,用于创建子菜单。

多选

使用 multiple 属性以允许多选。

<script setup lang="ts">
const groups = ref([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png'
        }
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        avatar: {
          src: 'https://github.com/danielroe.png'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png'
        }
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        avatar: {
          src: 'https://github.com/genu.png'
        }
      }
    ]
  }
])
const value = ref([])
</script>

<template>
  <UCommandPalette multiple v-model="value" :groups="groups" class="flex-1" />
</template>
请确保将数组传递给 default-value 属性或 v-model 指令。

占位符

使用 placeholder 属性来更改占位符文本。

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette placeholder="Search an app..." :groups="groups" class="flex-1" />
</template>

Icon

使用 icon 属性来自定义 Icon 组件的图标。默认为 i-lucide-search

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette icon="i-lucide-box" :groups="groups" class="flex-1" />
</template>
您可以在 app.config.ts 文件中,在 ui.icons.search 键下全局自定义此图标。
您可以在 vite.config.ts 文件中,在 ui.icons.search 键下全局自定义此图标。

选中图标

使用 selected-icon 属性来自定义选中项目的 Icon 组件。默认为 i-lucide-check

<script setup lang="ts">
const groups = ref([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png'
        }
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        avatar: {
          src: 'https://github.com/danielroe.png'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png'
        }
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        avatar: {
          src: 'https://github.com/genu.png'
        }
      }
    ]
  }
])
const value = ref([
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png'
    }
  }
])
</script>

<template>
  <UCommandPalette multiple v-model="value" selected-icon="i-lucide-circle-check" :groups="groups" class="flex-1" />
</template>
您可以在 app.config.ts 文件中,通过 ui.icons.check 键来全局自定义此图标。
您可以在 vite.config.ts 文件中,通过 ui.icons.check 键来全局自定义此图标。

尾部图标

使用 trailing-icon 属性来自定义当项目有子菜单时显示的尾部 Icon 组件。默认为 i-lucide-chevron-right

<script setup lang="ts">
const groups = ref([
  {
    id: 'actions',
    items: [
      {
        label: 'Share',
        icon: 'i-lucide-share',
        children: [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Copy',
            icon: 'i-lucide-copy'
          },
          {
            label: 'Link',
            icon: 'i-lucide-link'
          }
        ]
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette trailing-icon="i-lucide-arrow-right" :groups="groups" class="flex-1" />
</template>
您可以在 app.config.ts 文件中,在 ui.icons.chevronRight 键下全局自定义此图标。
您可以在 vite.config.ts 文件中,在 ui.icons.chevronRight 键下全局自定义此图标。

加载中

使用 loading 属性在 CommandPalette 上显示加载图标。

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette loading :groups="groups" class="flex-1" />
</template>

加载图标

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

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette loading loading-icon="i-lucide-loader" :groups="groups" class="flex-1" />
</template>
你可以在 app.config.ts 中的 ui.icons.loading 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.loading 键下全局自定义此图标。

关闭

使用 close 属性来显示一个 Button 组件以关闭 CommandPalette。

当点击关闭按钮时,会发出一个 update:open 事件。
<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette close :groups="groups" class="flex-1" />
</template>

您可以传递 Button 组件的任何属性来自定义它。

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette
    :close="{
      color: 'primary',
      variant: 'outline',
      class: 'rounded-full'
    }"
    :groups="groups"
    class="flex-1"
  />
</template>

关闭图标

使用 close-icon 属性自定义关闭按钮的 图标。默认为 i-lucide-x

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette close close-icon="i-lucide-arrow-right" :groups="groups" class="flex-1" />
</template>
你可以在 app.config.ts 中的 ui.icons.close 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.close 键下全局自定义此图标。

返回

使用 back 属性来自定义或隐藏在导航到子菜单时显示的后退按钮(使用 false 值)。

您可以传递 Button 组件的任何属性来自定义它。

<script setup lang="ts">
const groups = ref([
  {
    id: 'actions',
    items: [
      {
        label: 'Share',
        icon: 'i-lucide-share',
        children: [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Copy',
            icon: 'i-lucide-copy'
          },
          {
            label: 'Link',
            icon: 'i-lucide-link'
          }
        ]
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette
    :back="{
      color: 'primary'
    }"
    :groups="groups"
    class="flex-1"
  />
</template>

后退图标

使用 back-icon 属性来自定义后退按钮的 Icon 组件。默认为 i-lucide-arrow-left

<script setup lang="ts">
const groups = ref([
  {
    id: 'actions',
    items: [
      {
        label: 'Share',
        icon: 'i-lucide-share',
        children: [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Copy',
            icon: 'i-lucide-copy'
          },
          {
            label: 'Link',
            icon: 'i-lucide-link'
          }
        ]
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette back-icon="i-lucide-house" :groups="groups" class="flex-1" />
</template>
您可以在 app.config.ts 文件中,在 ui.icons.arrowLeft 键下全局自定义此图标。
您可以在 vite.config.ts 文件中,在 ui.icons.arrowLeft 键下全局自定义此图标。

禁用

使用 disabled 属性禁用 CommandPalette。

<script setup lang="ts">
const groups = ref([
  {
    id: 'apps',
    items: [
      {
        label: 'Calendar',
        icon: 'i-lucide-calendar'
      },
      {
        label: 'Music',
        icon: 'i-lucide-music'
      },
      {
        label: 'Maps',
        icon: 'i-lucide-map'
      }
    ]
  }
])
</script>

<template>
  <UCommandPalette disabled :groups="groups" class="flex-1" />
</template>

示例

控制选中的项目

您可以通过使用 default-value 属性或 v-model 指令,通过使用每个项目中的 onSelect 字段,或者通过 @update:model-value 事件来控制选中的项目。

<script setup lang="ts">
const toast = useToast()

const groups = ref([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        to: 'https://github.com/benjamincanac',
        target: '_blank',
        avatar: {
          src: 'https://github.com/benjamincanac.png'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        to: 'https://github.com/romhml',
        target: '_blank',
        avatar: {
          src: 'https://github.com/romhml.png'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        to: 'https://github.com/atinux',
        target: '_blank',
        avatar: {
          src: 'https://github.com/atinux.png'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        to: 'https://github.com/HugoRCD',
        target: '_blank',
        avatar: {
          src: 'https://github.com/HugoRCD.png'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        to: 'https://github.com/sandros94',
        target: '_blank',
        avatar: {
          src: 'https://github.com/sandros94.png'
        }
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        to: 'https://github.com/danielroe',
        target: '_blank',
        avatar: {
          src: 'https://github.com/danielroe.png'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        to: 'https://github.com/J-Michalek',
        target: '_blank',
        avatar: {
          src: 'https://github.com/J-Michalek.png'
        }
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        to: 'https://github.com/genu',
        target: '_blank',
        avatar: {
          src: 'https://github.com/genu.png'
        }
      }
    ]
  },
  {
    id: 'actions',
    items: [
      {
        label: 'Add new file',
        suffix: 'Create a new file in the current directory or workspace.',
        icon: 'i-lucide-file-plus',
        kbds: [
          'meta',
          'N'
        ],
        onSelect() {
          toast.add({ title: 'Add new file' })
        }
      },
      {
        label: 'Add new folder',
        suffix: 'Create a new folder in the current directory or workspace.',
        icon: 'i-lucide-folder-plus',
        kbds: [
          'meta',
          'F'
        ],
        onSelect() {
          toast.add({ title: 'Add new folder' })
        }
      },
      {
        label: 'Add hashtag',
        suffix: 'Add a hashtag to the current item.',
        icon: 'i-lucide-hash',
        kbds: [
          'meta',
          'H'
        ],
        onSelect() {
          toast.add({ title: 'Add hashtag' })
        }
      },
      {
        label: 'Add label',
        suffix: 'Add a label to the current item.',
        icon: 'i-lucide-tag',
        kbds: [
          'meta',
          'L'
        ],
        onSelect() {
          toast.add({ title: 'Add label' })
        }
      }
    ]
  }
])

function onSelect(item: any) {
  console.log(item)
}
</script>

<template>
  <UCommandPalette
    :groups="groups"
    class="flex-1 h-80"
    @update:model-value="onSelect"
  />
</template>

控制搜索词

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

<script setup lang="ts">
const users = [
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    to: 'https://github.com/benjamincanac',
    target: '_blank',
    avatar: {
      src: 'https://github.com/benjamincanac.png'
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png'
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png'
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png'
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png'
    }
  },
  {
    label: 'Daniel Roe',
    suffix: 'danielroe',
    to: 'https://github.com/danielroe',
    target: '_blank',
    avatar: {
      src: 'https://github.com/danielroe.png'
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png'
    }
  },
  {
    label: 'Eugen Istoc',
    suffix: 'genu',
    to: 'https://github.com/genu',
    target: '_blank',
    avatar: {
      src: 'https://github.com/genu.png'
    }
  }
]

const searchTerm = ref('B')

function onSelect() {
  searchTerm.value = ''
}
</script>

<template>
  <UCommandPalette
    v-model:search-term="searchTerm"
    :groups="[{ id: 'users', items: users }]"
    class="flex-1"
    @update:model-value="onSelect"
  />
</template>
此示例使用 @update:model-value 事件来重置选中项目时的搜索词。

项目包含子菜单

您可以通过使用项目中的 children 属性来创建分层菜单。当一个项目有子菜单时,它会自动显示一个箭头图标并启用导航到子菜单。

<script setup lang="ts">
const toast = useToast()

const groups = [
  {
    id: 'actions',
    label: 'Actions',
    items: [
      {
        label: 'Create new',
        icon: 'i-lucide-plus',
        children: [
          {
            label: 'New file',
            icon: 'i-lucide-file-plus',
            suffix: 'Create a new file in the current directory',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'New file created!' })
            },
            kbds: ['meta', 'N']
          },
          {
            label: 'New folder',
            icon: 'i-lucide-folder-plus',
            suffix: 'Create a new folder in the current directory',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'New folder created!' })
            },
            kbds: ['meta', 'F']
          },
          {
            label: 'New project',
            icon: 'i-lucide-folder-git',
            suffix: 'Create a new project from a template',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'New project created!' })
            },
            kbds: ['meta', 'P']
          }
        ]
      },
      {
        label: 'Share',
        icon: 'i-lucide-share',
        children: [
          {
            label: 'Copy link',
            icon: 'i-lucide-link',
            suffix: 'Copy a link to the current item',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'Link copied to clipboard!' })
            },
            kbds: ['meta', 'L']
          },
          {
            label: 'Share via email',
            icon: 'i-lucide-mail',
            suffix: 'Share the current item via email',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'Share via email dialog opened!' })
            }
          },
          {
            label: 'Share on social',
            icon: 'i-lucide-share-2',
            suffix: 'Share the current item on social media',
            children: [
              {
                label: 'Twitter',
                icon: 'i-simple-icons-twitter',
                onSelect(e: Event) {
                  e.preventDefault()
                  toast.add({ title: 'Shared on Twitter!' })
                }
              },
              {
                label: 'LinkedIn',
                icon: 'i-simple-icons-linkedin',
                onSelect(e: Event) {
                  e.preventDefault()
                  toast.add({ title: 'Shared on LinkedIn!' })
                }
              },
              {
                label: 'Facebook',
                icon: 'i-simple-icons-facebook',
                onSelect(e: Event) {
                  e.preventDefault()
                  toast.add({ title: 'Shared on Facebook!' })
                }
              }
            ]
          }
        ]
      },
      {
        label: 'Settings',
        icon: 'i-lucide-settings',
        children: [
          {
            label: 'General',
            icon: 'i-lucide-sliders',
            suffix: 'Configure general settings',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'General settings opened!' })
            }
          },
          {
            label: 'Appearance',
            icon: 'i-lucide-palette',
            suffix: 'Customize the appearance',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'Appearance settings opened!' })
            }
          },
          {
            label: 'Security',
            icon: 'i-lucide-shield',
            suffix: 'Manage security settings',
            onSelect(e: Event) {
              e.preventDefault()
              toast.add({ title: 'Security settings opened!' })
            }
          }
        ]
      }
    ]
  }
]
</script>

<template>
  <UCommandPalette :groups="groups" class="flex-1" />
</template>
导航到子菜单时
  • 搜索词会被重置
  • 输入框中会出现一个后退按钮
  • 您可以通过按 键返回到上一个组。

带获取的项

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

无数据
<script setup lang="ts">
const searchTerm = ref('')

const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users',
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []
  },
  lazy: true
})

const groups = computed(() => [{
  id: 'users',
  label: searchTerm.value ? `Users matching “${searchTerm.value}”...` : 'Users',
  items: users.value || []
}])
</script>

<template>
  <UCommandPalette
    v-model:search-term="searchTerm"
    :loading="status === 'pending'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>

带忽略过滤器

您可以在一个组上将 ignoreFilter 字段设置为 true,以禁用内部搜索并使用您自己的搜索逻辑。

无数据
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'

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, email: string }[]) => {
    return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []
  },
  lazy: true
})

const groups = computed(() => [{
  id: 'users',
  label: searchTerm.value ? `Users matching “${searchTerm.value}”...` : 'Users',
  items: users.value || [],
  ignoreFilter: true
}])
</script>

<template>
  <UCommandPalette
    v-model:search-term="searchTerm"
    :loading="status === 'pending'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>
此示例使用refDebounced来防抖 API 调用。

带后筛选的项目

您可以使用组上的 postFilter 字段在搜索发生后筛选项目。

<script setup lang="ts">
const items = [
  {
    id: '/',
    label: 'Introduction',
    level: 1
  },
  {
    id: '/docs/getting-started#whats-new-in-v3',
    label: 'What\'s new in v3?',
    level: 2
  },
  {
    id: '/docs/getting-started#reka-ui',
    label: 'Reka UI',
    level: 3
  },
  {
    id: '/docs/getting-started#tailwind-css-v4',
    label: 'Tailwind CSS v4',
    level: 3
  },
  {
    id: '/docs/getting-started#tailwind-variants',
    label: 'Tailwind Variants',
    level: 3
  },
  {
    id: '/docs/getting-started/installation',
    label: 'Installation',
    level: 1
  }
]

function postFilter(searchTerm: string, items: any[]) {
  // Filter only first level items if no searchTerm
  if (!searchTerm) {
    return items?.filter(item => item.level === 1)
  }

  return items
}
</script>

<template>
  <UCommandPalette :groups="[{ id: 'files', items, postFilter }]" class="flex-1" />
</template>
开始输入以查看更高级别的项目。

您可以使用 fuse 属性来覆盖useFuse默认情况下是

{
  fuseOptions: {
    ignoreLocation: true,
    threshold: 0.1,
    keys: ['label', 'suffix']
  },
  resultLimit: 12,
  matchAllWhenSearchEmpty: true
}
fuseOptions 是的选项Fuse.jsresultLimit 是要返回的最大结果数,而 matchAllWhenSearchEmpty 是一个布尔值,用于在搜索词为空时匹配所有项目。

例如,您可以设置 { fuseOptions: { includeMatches: true } } 来高亮显示搜索词。

无数据
<script setup lang="ts">
const { data: users } = await useFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users',
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []
  },
  lazy: true
})
</script>

<template>
  <UCommandPalette
    :groups="[{ id: 'users', items: users || [] }]"
    :fuse="{ fuseOptions: { includeMatches: true } }"
    class="flex-1 h-80"
  />
</template>

虚拟化 即将推出

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

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

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

const groups = [
  {
    id: 'items',
    items
  }
]
</script>

<template>
  <UCommandPalette
    virtualize
    :fuse="{ resultLimit: 1000 }"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>

在 Popover 中

您可以在 Popover 组件的内容中使用 CommandPalette 组件。

<script setup lang="ts">
const items = ref([
  {
    label: 'bug',
    value: 'bug',
    chip: {
      color: 'error' as const
    }
  },
  {
    label: 'feature',
    value: 'feature',
    chip: {
      color: 'success' as const
    }
  },
  {
    label: 'enhancement',
    value: 'enhancement',
    chip: {
      color: 'info' as const
    }
  }
])
const label = ref([])
</script>

<template>
  <UPopover :content="{ side: 'right', align: 'start' }">
    <UButton
      icon="i-lucide-tag"
      label="Select labels"
      color="neutral"
      variant="subtle"
    />

    <template #content>
      <UCommandPalette
        v-model="label"
        multiple
        placeholder="Search labels..."
        :groups="[{ id: 'labels', items }]"
        :ui="{ input: '[&>input]:h-8 [&>input]:text-sm' }"
      />
    </template>
  </UPopover>
</template>

在 Modal 中

您可以在 Modal 组件的内容中使用 CommandPalette 组件。

<script setup lang="ts">
const searchTerm = ref('')

const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users',
  params: { q: searchTerm },
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []
  },
  lazy: true
})

const groups = computed(() => [{
  id: 'users',
  label: searchTerm.value ? `Users matching “${searchTerm.value}”...` : 'Users',
  items: users.value || [],
  ignoreFilter: true
}])
</script>

<template>
  <UModal>
    <UButton
      label="Search users..."
      color="neutral"
      variant="subtle"
      icon="i-lucide-search"
    />

    <template #content>
      <UCommandPalette
        v-model:search-term="searchTerm"
        :loading="status === 'pending'"
        :groups="groups"
        placeholder="Search users..."
        class="h-80"
      />
    </template>
  </UModal>
</template>

在 Drawer 中

您可以在 Drawer 组件的内容中使用 CommandPalette 组件。

<script setup lang="ts">
const searchTerm = ref('')

const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users',
  params: { q: searchTerm },
  transform: (data: { id: number, name: string, email: string }[]) => {
    return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []
  },
  lazy: true
})

const groups = computed(() => [{
  id: 'users',
  label: searchTerm.value ? `Users matching “${searchTerm.value}”...` : 'Users',
  items: users.value || [],
  ignoreFilter: true
}])
</script>

<template>
  <UDrawer :handle="false">
    <UButton
      label="Search users..."
      color="neutral"
      variant="subtle"
      icon="i-lucide-search"
    />

    <template #content>
      <UCommandPalette
        v-model:search-term="searchTerm"
        :loading="status === 'pending'"
        :groups="groups"
        placeholder="Search users..."
        class="h-80"
      />
    </template>
  </UDrawer>
</template>

监听 open 状态

当使用 close 属性时,您可以在点击按钮时监听 update:open 事件。

<script setup lang="ts">
const open = ref(false)

const users = [
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    to: 'https://github.com/benjamincanac',
    target: '_blank',
    avatar: {
      src: 'https://github.com/benjamincanac.png'
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png'
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png'
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png'
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png'
    }
  },
  {
    label: 'Daniel Roe',
    suffix: 'danielroe',
    to: 'https://github.com/danielroe',
    target: '_blank',
    avatar: {
      src: 'https://github.com/danielroe.png'
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png'
    }
  },
  {
    label: 'Eugen Istoc',
    suffix: 'genu',
    to: 'https://github.com/genu',
    target: '_blank',
    avatar: {
      src: 'https://github.com/genu.png'
    }
  }
]
</script>

<template>
  <UModal v-model:open="open">
    <UButton
      label="Search users..."
      color="neutral"
      variant="subtle"
      icon="i-lucide-search"
    />

    <template #content>
      <UCommandPalette close :groups="[{ id: 'users', items: users }]" @update:open="open = $event" />
    </template>
  </UModal>
</template>
当 CommandPalette 放在 Modal 中时,这会很有用。

使用 #footer 插槽在 CommandPalette 的底部添加自定义内容,例如键盘快捷键帮助或附加操作。

<script setup lang="ts">
const groups = [
  {
    id: 'actions',
    items: [
      {
        label: 'Add new file',
        suffix: 'Create a new file in the current directory',
        icon: 'i-lucide-file-plus',
        kbds: ['meta', 'N']
      },
      {
        label: 'Add new folder',
        suffix: 'Create a new folder in the current directory',
        icon: 'i-lucide-folder-plus',
        kbds: ['meta', 'F']
      },
      {
        label: 'Search files',
        suffix: 'Search across all files in the project',
        icon: 'i-lucide-search',
        kbds: ['meta', 'P']
      },
      {
        label: 'Settings',
        suffix: 'Open application settings',
        icon: 'i-lucide-settings',
        kbds: ['meta', ',']
      }
    ]
  },
  {
    id: 'recent',
    label: 'Recent',
    items: [
      {
        label: 'project.vue',
        suffix: 'components/',
        icon: 'i-vscode-icons-file-type-vue'
      },
      {
        label: 'readme.md',
        suffix: 'docs/',
        icon: 'i-vscode-icons-file-type-markdown'
      },
      {
        label: 'package.json',
        suffix: 'root/',
        icon: 'i-vscode-icons-file-type-node'
      }
    ]
  }
]
</script>

<template>
  <UCommandPalette :groups="groups" class="flex-1 h-80">
    <template #footer>
      <div class="flex items-center justify-between gap-2">
        <UIcon name="i-simple-icons-nuxtdotjs" class="size-5 text-dimmed ml-1" />
        <div class="flex items-center gap-1">
          <UButton color="neutral" variant="ghost" label="Open Command" class="text-dimmed" size="xs">
            <template #trailing>
              <UKbd value="enter" />
            </template>
          </UButton>
          <USeparator orientation="vertical" class="h-4" />
          <UButton color="neutral" variant="ghost" label="Actions" class="text-dimmed" size="xs">
            <template #trailing>
              <UKbd value="meta" />
              <UKbd value="k" />
            </template>
          </UButton>
        </div>
      </div>
    </template>
  </UCommandPalette>
</template>

带自定义插槽

使用 slot 属性来自定义特定项目或组。

您将可以使用以下插槽

  • #{{ item.slot }}
  • #{{ item.slot }}-leading
  • #{{ item.slot }}-label
  • #{{ item.slot }}-trailing
  • #{{ group.slot }}
  • #{{ group.slot }}-leading
  • #{{ group.slot }}-label
  • #{{ group.slot }}-trailing
<script setup lang="ts">
const groups = [
  {
    id: 'settings',
    items: [
      {
        label: 'Profile',
        icon: 'i-lucide-user',
        kbds: ['meta', 'P']
      },
      {
        label: 'Billing',
        icon: 'i-lucide-credit-card',
        kbds: ['meta', 'B'],
        slot: 'billing' as const
      },
      {
        label: 'Notifications',
        icon: 'i-lucide-bell'
      },
      {
        label: 'Security',
        icon: 'i-lucide-lock'
      }
    ]
  },
  {
    id: 'users',
    label: 'Users',
    slot: 'users' as const,
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        to: 'https://github.com/benjamincanac',
        target: '_blank'
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        to: 'https://github.com/romhml',
        target: '_blank'
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        to: 'https://github.com/atinux',
        target: '_blank'
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        to: 'https://github.com/HugoRCD',
        target: '_blank'
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        to: 'https://github.com/sandros94',
        target: '_blank'
      },
      {
        label: 'Daniel Roe',
        suffix: 'danielroe',
        to: 'https://github.com/danielroe',
        target: '_blank'
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        to: 'https://github.com/J-Michalek',
        target: '_blank'
      },
      {
        label: 'Eugen Istoc',
        suffix: 'genu',
        to: 'https://github.com/genu',
        target: '_blank'
      }
    ]
  }
]
</script>

<template>
  <UCommandPalette :groups="groups" class="flex-1 h-80">
    <template #users-leading="{ item }">
      <UAvatar :src="`https://github.com/${item.suffix}.png`" size="2xs" />
    </template>

    <template #billing-label="{ item }">
      <span class="font-medium text-primary">{{ item.label }}</span>

      <UBadge variant="subtle" size="sm">
        50% off
      </UBadge>
    </template>
  </UCommandPalette>
</template>
您还可以使用 #item#item-leading#item-label#item-trailing 插槽来自定义所有项。

API

属性

属性默认值类型
as

'div'

any

此组件应渲染为的元素或组件。

图标

appConfig.ui.icons.search

字符串 | 对象

输入框中显示的图标。

selectedIcon

appConfig.ui.icons.check

字符串 | 对象

选中项时显示的图标。

trailingIcon

appConfig.ui.icons.chevronRight

字符串 | 对象

项目包含子菜单时显示的图标。

placeholder

t('commandPalette.placeholder')

string

输入框的占位文本。

autofocus

true

boolean

组件挂载时自动聚焦输入框。

close

false

布尔值 | 部分<ButtonProps>

显示一个关闭按钮在输入框中(例如,当在 Modal 中时很有用)。{ size: 'md', color: 'neutral', variant: 'ghost' }

closeIcon

appConfig.ui.icons.close

字符串 | 对象

关闭按钮中显示的图标。

返回

true

boolean | ButtonProps

显示一个按钮用于导航历史记录。 { size: 'md', color: 'neutral', variant: 'link' }

backIcon

appConfig.ui.icons.arrowLeft

字符串 | 对象

后退按钮中显示的图标。

分组

CommandPaletteGroup<CommandPaletteItem>[]

fuse

{ fuseOptions: { ignoreLocation: true, threshold: 0.1, keys: ['label', 'suffix'] }, resultLimit: 12, matchAllWhenSearchEmpty: true }

UseFuseOptions<CommandPaletteItem>

用于 `useFuse` 的选项useFuse.

virtualize

false

boolean |{ overscan?: number ; estimateSize?: number | undefined; } | undefined

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

labelKey

'label'

string | number

用于从项中获取标签的键。

multiple

boolean

是否可以选择多个选项。

disabled

boolean

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

modelValue

''

null | string | number | bigint | Record<string, any> | AcceptableValue[]

列表框的受控值。可以使用 v-model 进行绑定。

defaultValue

null | string | number | bigint | Record<string, any> | AcceptableValue[]

Listbox 初始渲染时的值。在不需要控制 Listbox 状态时使用。

highlightOnHover

boolean

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

selectionBehavior

'toggle'

"replace" | "toggle"

多选在集合中的行为。

loading

boolean

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

loadingIcon

appConfig.ui.icons.loading

字符串 | 对象

loading prop 为 true 时显示的图标。

搜索词

''

string

ui

{ root?: ClassNameValue; input?: ClassNameValue; close?: ClassNameValue; back?: ClassNameValue; content?: ClassNameValue; footer?: ClassNameValue; viewport?: ClassNameValue; group?: ClassNameValue; empty?: ClassNameValue; label?: ClassNameValue; item?: ClassNameValue; itemLeadingIcon?: ClassNameValue; itemLeadingAvatar?: ClassNameValue; itemLeadingAvatarSize?: ClassNameValue; itemLeadingChip?: ClassNameValue; itemLeadingChipSize?: ClassNameValue; itemTrailing?: ClassNameValue; itemTrailingIcon?: ClassNameValue; itemTrailingHighlightedIcon?: ClassNameValue; itemTrailingKbds?: ClassNameValue; itemTrailingKbdsSize?: ClassNameValue; itemLabel?: ClassNameValue; itemLabelBase?: ClassNameValue; itemLabelPrefix?: ClassNameValue; itemLabelSuffix?: ClassNameValue; }

插槽

插槽类型

{ searchTerm?: string | undefined; }

页脚

{ ui: {}; }

返回

{ ui: {}; }

close

{ ui: {}; }

item

{ item: CommandPaletteItem; index: number; }

item-leading

{ item: CommandPaletteItem; index: number; }

item-label

{ item: CommandPaletteItem; index: number; }

item-trailing

{ item: CommandPaletteItem; index: number; }

事件

事件类型
update:modelValue

[value: CommandPaletteItem]

高亮

[payload: { ref: HTMLElement; value: CommandPaletteItem; } | undefined]

entryFocus

[event: CustomEvent<any>]

leave

[event: Event]

update:open

[value: boolean]

update:searchTerm

[value: string]

主题

app.config.ts
export default defineAppConfig({
  ui: {
    commandPalette: {
      slots: {
        root: 'flex flex-col min-h-0 min-w-0 divide-y divide-default',
        input: '[&>input]:h-12',
        close: '',
        back: 'p-0',
        content: 'relative overflow-hidden flex flex-col',
        footer: 'p-1',
        viewport: 'relative scroll-py-1 overflow-y-auto flex-1 focus:outline-none',
        group: 'p-1 isolate',
        empty: 'py-6 text-center text-sm text-muted',
        label: 'p-1.5 text-xs font-semibold text-highlighted',
        item: 'group relative w-full flex items-center 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',
        itemLeadingIcon: 'shrink-0 size-5',
        itemLeadingAvatar: 'shrink-0',
        itemLeadingAvatarSize: '2xs',
        itemLeadingChip: 'shrink-0 size-5',
        itemLeadingChipSize: 'md',
        itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
        itemTrailingIcon: 'shrink-0 size-5',
        itemTrailingHighlightedIcon: 'shrink-0 size-5 text-dimmed hidden group-data-highlighted:inline-flex',
        itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
        itemTrailingKbdsSize: 'md',
        itemLabel: 'truncate space-x-1 text-dimmed',
        itemLabelBase: 'text-highlighted [&>mark]:text-inverted [&>mark]:bg-primary',
        itemLabelPrefix: 'text-default',
        itemLabelSuffix: 'text-dimmed [&>mark]:text-inverted [&>mark]:bg-primary'
      },
      variants: {
        virtualize: {
          true: {
            viewport: 'p-1 isolate'
          },
          false: {
            viewport: 'divide-y divide-default'
          }
        },
        active: {
          true: {
            item: 'text-highlighted before:bg-elevated',
            itemLeadingIcon: 'text-default'
          },
          false: {
            item: [
              'text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
              'transition-colors before:transition-colors'
            ],
            itemLeadingIcon: [
              'text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
              'transition-colors'
            ]
          }
        },
        loading: {
          true: {
            itemLeadingIcon: 'animate-spin'
          }
        }
      }
    }
  }
})
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: {
        commandPalette: {
          slots: {
            root: 'flex flex-col min-h-0 min-w-0 divide-y divide-default',
            input: '[&>input]:h-12',
            close: '',
            back: 'p-0',
            content: 'relative overflow-hidden flex flex-col',
            footer: 'p-1',
            viewport: 'relative scroll-py-1 overflow-y-auto flex-1 focus:outline-none',
            group: 'p-1 isolate',
            empty: 'py-6 text-center text-sm text-muted',
            label: 'p-1.5 text-xs font-semibold text-highlighted',
            item: 'group relative w-full flex items-center 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',
            itemLeadingIcon: 'shrink-0 size-5',
            itemLeadingAvatar: 'shrink-0',
            itemLeadingAvatarSize: '2xs',
            itemLeadingChip: 'shrink-0 size-5',
            itemLeadingChipSize: 'md',
            itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
            itemTrailingIcon: 'shrink-0 size-5',
            itemTrailingHighlightedIcon: 'shrink-0 size-5 text-dimmed hidden group-data-highlighted:inline-flex',
            itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
            itemTrailingKbdsSize: 'md',
            itemLabel: 'truncate space-x-1 text-dimmed',
            itemLabelBase: 'text-highlighted [&>mark]:text-inverted [&>mark]:bg-primary',
            itemLabelPrefix: 'text-default',
            itemLabelSuffix: 'text-dimmed [&>mark]:text-inverted [&>mark]:bg-primary'
          },
          variants: {
            virtualize: {
              true: {
                viewport: 'p-1 isolate'
              },
              false: {
                viewport: 'divide-y divide-default'
              }
            },
            active: {
              true: {
                item: 'text-highlighted before:bg-elevated',
                itemLeadingIcon: 'text-default'
              },
              false: {
                item: [
                  'text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
                  'transition-colors before:transition-colors'
                ],
                itemLeadingIcon: [
                  'text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
                  'transition-colors'
                ]
              }
            },
            loading: {
              true: {
                itemLeadingIcon: 'animate-spin'
              }
            }
          }
        }
      }
    })
  ]
})

更新日志

84f87— feat: 添加全局事件处理程序和复选框示例 (#5195)

c744d— feat: implement virtualization (#5162)

11a03— fix: labelKeyvalueKey 的点表示法类型支持 (#4933)

61b60— 功能:允许传递组件而不是名称 (#4766)

5cb65— 特性:导入 @nuxt/ui-pro 组件

63730— feat: add footer slot (#4457)

be41a— 修复:移除按钮默认md尺寸 (#4357)

59c26— feat: handle children in items (#4226)

2ba94— fix: add presentation role to viewport

b9adc— feat: 在 items 中添加 ui 字段 (#4060)

e6e51— fix:class 应该优先于 ui 属性

39c86— fix:@nuxt/module-builder 升级后重构类型(#3855)

d2526— fix: consistent alignement with other components

bc61d— fix: use group.id as key

06dfb— chore: improve placeholder tsdoc

b9983— 修复:改进泛型类型 (#3331)

ef861— chore: 在 script 标签中添加 eol 以修复语法高亮