用法
使用 v-model
指令控制 CommandPalette 的值,或者使用 default-value
prop 设置初始值,当您不需要控制其状态时。
分组
CommandPalette 组件会过滤分组并根据用户输入的相关性对匹配的命令进行排序。它提供动态、即时搜索结果,以实现高效的命令发现。使用 groups
prop 作为包含以下属性的对象数组:
id: string
label?: string
slot?: string
items?: CommandPaletteItem[]
ignoreFilter?: boolean
postFilter?: (searchTerm: string, items: T[]) => T[]
highlightedIcon?: string
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
onSelect?(e?: Event): void
您可以传递 Link 组件的任何属性,例如 to
、target
等。
<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: 'Sylvain Marroufin',
suffix: 'smarroufin',
avatar: {
src: 'https://github.com/smarroufin.png'
}
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'Romain Hamel',
suffix: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
avatar: {
src: 'https://github.com/Haythamasalama.png'
}
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
avatar: {
src: 'https://github.com/danielroe.png'
}
},
{
label: 'Neil Richter',
suffix: 'noook',
avatar: {
src: 'https://github.com/noook.png'
}
}
]
}
])
const value = ref({})
</script>
<template>
<UCommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
多选
使用 multiple
prop 允许进行多项选择。
<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: 'Sylvain Marroufin',
suffix: 'smarroufin',
avatar: {
src: 'https://github.com/smarroufin.png'
}
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'Romain Hamel',
suffix: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
avatar: {
src: 'https://github.com/Haythamasalama.png'
}
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
avatar: {
src: 'https://github.com/danielroe.png'
}
},
{
label: 'Neil Richter',
suffix: 'noook',
avatar: {
src: 'https://github.com/noook.png'
}
}
]
}
])
const value = ref([])
</script>
<template>
<UCommandPalette multiple v-model="value" :groups="groups" class="flex-1" />
</template>
default-value
prop 或 v-model
指令。占位符
使用 placeholder
prop 修改占位符文本。
<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
prop 自定义输入框 图标。默认为 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>
加载中
使用 loading
prop 在 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-refresh-cw
。
<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-repeat-2" :groups="groups" class="flex-1" />
</template>
禁用
使用 disabled
prop 禁用 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>
关闭
使用 close
prop 显示一个 按钮 以关闭 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
prop 自定义关闭按钮 图标。默认为 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>
示例
控制选定的项
您可以通过使用 default-value
prop 或 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: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank',
avatar: {
src: 'https://github.com/smarroufin.png'
}
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank',
avatar: {
src: 'https://github.com/Haythamasalama.png'
}
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank',
avatar: {
src: 'https://github.com/danielroe.png'
}
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
target: '_blank',
avatar: {
src: 'https://github.com/noook.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: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank',
avatar: {
src: 'https://github.com/smarroufin.png'
}
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank',
avatar: {
src: 'https://github.com/Haythamasalama.png'
}
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank',
avatar: {
src: 'https://github.com/danielroe.png'
}
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
target: '_blank',
avatar: {
src: 'https://github.com/noook.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
事件在选择项后重置搜索词。使用获取的项
您可以从 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">
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'command-palette-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: '/getting-started#whats-new-in-v3',
label: 'What\'s new in v3?',
level: 2
},
{
id: '/getting-started#reka-ui',
label: 'Reka UI',
level: 3
},
{
id: '/getting-started#tailwind-css-v4',
label: 'Tailwind CSS v4',
level: 3
},
{
id: '/getting-started#tailwind-variants',
label: 'Tailwind Variants',
level: 3
},
{
id: '/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 搜索
您可以使用 fuse
prop 覆盖以下选项:useFuse默认为
{
fuseOptions: {
ignoreLocation: true,
threshold: 0.1,
keys: ['label', 'suffix']
},
resultLimit: 12,
matchAllWhenSearchEmpty: true
}
例如,您可以设置 { 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>
在气泡框中
您可以在 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 的内容中使用 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 的内容中使用 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>
监听打开状态
使用 close
prop 时,您可以在按钮点击时监听 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: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank',
avatar: {
src: 'https://github.com/smarroufin.png'
}
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank',
avatar: {
src: 'https://github.com/romhml.png'
}
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank',
avatar: {
src: 'https://github.com/Haythamasalama.png'
}
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank',
avatar: {
src: 'https://github.com/danielroe.png'
}
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
target: '_blank',
avatar: {
src: 'https://github.com/noook.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>
Modal
内部使用 CommandPalette 时,这会很有用。使用自定义槽
使用 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: 'Sylvain Marroufin',
suffix: 'smarroufin',
to: 'https://github.com/smarroufin',
target: '_blank'
},
{
label: 'Sébastien Chopin',
suffix: 'atinux',
to: 'https://github.com/atinux',
target: '_blank'
},
{
label: 'Romain Hamel',
suffix: 'romhml',
to: 'https://github.com/romhml',
target: '_blank'
},
{
label: 'Haytham A. Salama',
suffix: 'Haythamasalama',
to: 'https://github.com/Haythamasalama',
target: '_blank'
},
{
label: 'Daniel Roe',
suffix: 'danielroe',
to: 'https://github.com/danielroe',
target: '_blank'
},
{
label: 'Neil Richter',
suffix: 'noook',
to: 'https://github.com/noook',
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 }">
{{ item.label }}
<UBadge variant="subtle" size="sm">
50% off
</UBadge>
</template>
</UCommandPalette>
</template>
API
属性
属性 | 默认值 | 类型 |
---|---|---|
as |
|
此组件应渲染为的元素或组件。 |
图标 |
|
输入框中显示的图标。 |
selectedIcon |
|
选中项目时显示的图标。 |
占位符 |
|
输入框的占位符文本。 |
autofocus |
|
组件挂载时自动聚焦输入框。 |
close |
|
在输入框中显示关闭按钮(例如,在 Modal 内部时很有用)。 |
closeIcon |
|
关闭按钮中显示的图标。 |
groups |
| |
fuse |
|
选项useFuse. |
labelKey |
|
用于从项目中获取标签的键。 |
multiple |
是否可以选择多个选项。 | |
禁用 |
当 | |
modelValue |
|
列表框的受控值。可以与 |
defaultValue |
列表框初始渲染时的值。当您不需要控制 Listbox 的状态时使用 | |
highlightOnHover |
当 | |
加载中 |
当 | |
loadingIcon |
|
当 |
searchTerm |
|
|
ui |
|
槽
槽 | 类型 |
---|---|
empty |
|
close |
|
item |
|
item-leading |
|
item-label |
|
item-trailing |
|
事件
事件 | 类型 |
---|---|
update:modelValue |
|
highlight |
|
entryFocus |
|
leave |
|
update:open |
|
update:searchTerm |
|
主题
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: '',
content: 'relative overflow-hidden flex flex-col',
viewport: 'relative divide-y divide-default 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 rtl:space-x-reverse text-dimmed',
itemLabelBase: 'text-highlighted [&>mark]:text-inverted [&>mark]:bg-primary',
itemLabelPrefix: 'text-default',
itemLabelSuffix: 'text-dimmed [&>mark]:text-inverted [&>mark]:bg-primary'
},
variants: {
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'
}
}
}
}
}
})
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: '',
content: 'relative overflow-hidden flex flex-col',
viewport: 'relative divide-y divide-default 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 rtl:space-x-reverse text-dimmed',
itemLabelBase: 'text-highlighted [&>mark]:text-inverted [&>mark]:bg-primary',
itemLabelPrefix: 'text-default',
itemLabelSuffix: 'text-dimmed [&>mark]:text-inverted [&>mark]:bg-primary'
},
variants: {
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'
}
}
}
}
}
})
]
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'
export default defineConfig({
plugins: [
vue(),
uiPro({
ui: {
commandPalette: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 divide-y divide-default',
input: '[&>input]:h-12',
close: '',
content: 'relative overflow-hidden flex flex-col',
viewport: 'relative divide-y divide-default 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 rtl:space-x-reverse text-dimmed',
itemLabelBase: 'text-highlighted [&>mark]:text-inverted [&>mark]:bg-primary',
itemLabelPrefix: 'text-default',
itemLabelSuffix: 'text-dimmed [&>mark]:text-inverted [&>mark]:bg-primary'
},
variants: {
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'
}
}
}
}
}
})
]
})