Commandée

Une palette de commandes avec recherche en texte intégral optimisée par Fuse.js pour une correspondance floue efficace.

Utilisation

Utilisez la directive v-model pour contrôler la valeur de la CommandPalette ou la prop default-value pour définir la valeur initiale lorsque vous n'avez pas besoin de contrôler son état.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1 h-80" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1 h-80" />
</template>
Vous pouvez également utiliser l'événement @update:model-value pour écouter le ou les éléments sélectionnés.

Groupes

Le composant CommandPalette filtre les groupes et classe les commandes correspondantes en fonction de leur pertinence au fur et à mesure que les utilisateurs tapent. Il fournit des résultats de recherche dynamiques et instantanés pour une découverte efficace des commandes. Utilisez le prop groups comme un tableau d'objets avec les propriétés suivantes:

Vous devez fournir un id pour chaque groupe sinon le groupe sera ignoré.

Chaque groupe contient un tableau items d'objets qui définissent les commandes. Chaque élément peut avoir les propriétés suivantes:

  • xprefix?: stringx{lang="ts-type"}
  • xlabel?: stringx{lang="ts-type"}
  • xsuffix?: stringx{lang="ts-type"}
  • icon?: string
  • xavatar?: AvatarPropsx{lang="ts-type"}
  • xchip?: ChipPropsx{lang="ts-type"}
  • xkbds?: string[] | KbdProps[]x{lang="ts-type"}
  • active?: booleanx{lang="ts-type"}
  • xloading?: booleanx{lang="ts-type"}
  • xdisabled?: booleanx{lang="ts-type"}
  • xxslot?: stringx{lang="ts-type"}x
  • xplaceholder?: stringx{lang="ts-type"}
  • xchildren?: CommandPaletteItem[]x{lang="ts-type"}
  • xonSelect?: (e: Event) => voidx{lang="ts-type"}
  • xclass?: anyx{lang="ts-type"}
  • xui?: { 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 }x{lang="ts-type"}

Vous pouvez passer n'importe quelle propriété du composant Link telle que to, target, etc.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref({})
</script>

<template>
  <UCommandPalette v-model="value" :groups="groups" class="flex-1" />
</template>
Chaque élément peut prendre un tableau d'objets children avec les propriétés suivantes pour créer des sous-menus:

Multiple

Utilisez le prop multiple pour permettre plusieurs sélections.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref([])
</script>

<template>
  <UCommandPalette multiple v-model="value" :groups="groups" class="flex-1" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref([])
</script>

<template>
  <UCommandPalette multiple v-model="value" :groups="groups" class="flex-1" />
</template>
Assurez-vous de passer un tableau à la prop default-value ou à la directive v-model.

Placeholder électronique

Utilisez la prop placeholder pour modifier le texte de l'espace réservé.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>

Taille: badge{label="4.4+" class="align-text-top"}

Utilisez la prop size pour modifier la taille de la CommandPalette.

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

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

<template>
  <UCommandPalette size="xl" :groups="groups" class="flex-1" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

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

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

Icône

Utilisez la prop icon pour personnaliser l'entrée Icon.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la clé ui.icons.search.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.search.

Selected Icône sélectionné

Utilisez la prop selected-icon pour personnaliser l'élément sélectionné Icon. Par défaut à i-lucide-check.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref([
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png',
      loading: 'lazy'
    }
  }
])
</script>

<template>
  <UCommandPalette multiple v-model="value" selected-icon="i-lucide-circle-check" :groups="groups" class="flex-1" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    id: 'users',
    label: 'Users',
    items: [
      {
        label: 'Benjamin Canac',
        suffix: 'benjamincanac',
        avatar: {
          src: 'https://github.com/benjamincanac.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy'
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy'
        }
      }
    ]
  }
])
const value = ref([
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    avatar: {
      src: 'https://github.com/benjamincanac.png',
      loading: 'lazy'
    }
  }
])
</script>

<template>
  <UCommandPalette multiple v-model="value" selected-icon="i-lucide-circle-check" :groups="groups" class="flex-1" />
</template>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la touche ui.icons.check.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.check.

Icône ### Trailing

Use the trailing-icon prop to customize the trailing Icon when an item has children.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la touche ui.icons.chevronRight.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la clé ui.icons.chevronRight.

Chargement

Utilisez le prop loading pour afficher une icône de chargement sur la CommandPalette.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>

Chargement Icône

Utilisez la prop loading-icon pour personnaliser l'icône de chargement. Par défaut, i-lucide-loader-circle.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la touche ui.icons.loading.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.loading.

Fermer

Utilisez la prop close pour afficher un Button pour supprimer la CommandPalette.

Un événement update:open sera émis lorsque le bouton Fermer est cliqué.
<script setup lang="ts">
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>

Vous pouvez passer n'importe quelle propriété du composant Button pour le personnaliser.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>

Fermer l'icône

Use the close-icon prop to customize the close button Icon.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
You can customize this icon globally in your app.config.ts under ui.icons.close key.
You can customize this icon globally in your vite.config.ts under ui.icons.close key.

Retour

Utilisez la prop back pour personnaliser ou masquer le bouton retour (avec la valeur false) affiché lors de la navigation dans un sous-menu.

Vous pouvez passer n'importe quelle propriété du composant Button pour la personnaliser.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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 Icône

Utilisez le prop back-icon pour personnaliser le bouton retour Icon. Par défaut, i-lucide-arrow-left.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la touche ui.icons.arrowLeft.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.arrowLeft.

Désactivé

Utilisez la prop disabled pour désactiver la CommandPalette.

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

const groups = ref<CommandPaletteGroup[]>([
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteGroup } from '@nuxt/ui'

const groups = ref<CommandPaletteGroup[]>([
  {
    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>

Exemples

Control élément sélectionné (s)

Vous pouvez contrôler le ou les éléments sélectionnés en utilisant la prop default-value ou la directive v-model, en utilisant le champ onSelect sur chaque élément ou en utilisant l'événement @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',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        to: 'https://github.com/HugoRCD',
        target: '_blank',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        to: 'https://github.com/atinux',
        target: '_blank',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        to: 'https://github.com/romhml',
        target: '_blank',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        to: 'https://github.com/sandros94',
        target: '_blank',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        to: 'https://github.com/J-Michalek',
        target: '_blank',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        to: 'https://github.com/hywax',
        target: '_blank',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        to: 'https://github.com/maximepvrt',
        target: '_blank',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy' as const
        }
      }
    ]
  },
  {
    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>
<script setup lang="ts">
import { ref } from 'vue'

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',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Hugo Richard',
        suffix: 'HugoRCD',
        to: 'https://github.com/HugoRCD',
        target: '_blank',
        avatar: {
          src: 'https://github.com/HugoRCD.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Sébastien Chopin',
        suffix: 'atinux',
        to: 'https://github.com/atinux',
        target: '_blank',
        avatar: {
          src: 'https://github.com/atinux.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Romain Hamel',
        suffix: 'romhml',
        to: 'https://github.com/romhml',
        target: '_blank',
        avatar: {
          src: 'https://github.com/romhml.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Sandro Circi',
        suffix: 'sandros94',
        to: 'https://github.com/sandros94',
        target: '_blank',
        avatar: {
          src: 'https://github.com/sandros94.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Jakub Michálek',
        suffix: 'J-Michalek',
        to: 'https://github.com/J-Michalek',
        target: '_blank',
        avatar: {
          src: 'https://github.com/J-Michalek.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Alex',
        suffix: 'hywax',
        to: 'https://github.com/hywax',
        target: '_blank',
        avatar: {
          src: 'https://github.com/hywax.png',
          loading: 'lazy' as const
        }
      },
      {
        label: 'Maxime Pauvert',
        suffix: 'maximepvrt',
        to: 'https://github.com/maximepvrt',
        target: '_blank',
        avatar: {
          src: 'https://github.com/maximepvrt.png',
          loading: 'lazy' as const
        }
      }
    ]
  },
  {
    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>
Utilisez la prop value-key pour sélectionner un champ d'un élément à utiliser comme valeur au lieu de l'objet lui-même. Utilisez la prop by pour comparer des objets par un champ au lieu de référence.

Control terme de recherche

Utilisez la directive v-model:search-term pour contrôler le terme de recherche.

<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',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Alex',
    suffix: 'hywax',
    to: 'https://github.com/hywax',
    target: '_blank',
    avatar: {
      src: 'https://github.com/hywax.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Maxime Pauvert',
    suffix: 'maximepvrt',
    to: 'https://github.com/maximepvrt',
    target: '_blank',
    avatar: {
      src: 'https://github.com/maximepvrt.png',
      loading: 'lazy' as const
    }
  }
]

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>
<script setup lang="ts">
import { ref } from 'vue'

const users = [
  {
    label: 'Benjamin Canac',
    suffix: 'benjamincanac',
    to: 'https://github.com/benjamincanac',
    target: '_blank',
    avatar: {
      src: 'https://github.com/benjamincanac.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Alex',
    suffix: 'hywax',
    to: 'https://github.com/hywax',
    target: '_blank',
    avatar: {
      src: 'https://github.com/hywax.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Maxime Pauvert',
    suffix: 'maximepvrt',
    to: 'https://github.com/maximepvrt',
    target: '_blank',
    avatar: {
      src: 'https://github.com/maximepvrt.png',
      loading: 'lazy' as const
    }
  }
]

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>
Cet exemple utilise l'événement @update:model-value pour réinitialiser le terme de recherche lorsqu 'un élément est sélectionné.

Avec les enfants dans les articles

Vous pouvez créer des menus hiérarchiques à l'aide de la propriété children dans les éléments. Lorsqu 'un élément a des enfants, il affiche automatiquement une icône de chevron et permet la navigation dans un sous-menu.

<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>
Lorsque vous naviguez dans un sous-menu:
  • Le terme de recherche est réinitialisé Le bouton retour - A apparaît dans l'entrée
  • Vous pouvez revenir au groupe précédent en appuyant sur: kbd{value="backspace"} touche

Avec les éléments récupérés

Vous pouvez récupérer des éléments à partir d'une API et les utiliser dans la CommandPalette.

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

const { data: users, status } = useLazyFetch('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}`, loading: 'lazy' as const } })) || []
  },
  server: false
})

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' || status === 'idle'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'

const searchTerm = ref('')

const { data: users, status } = useLazyFetch('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}`, loading: 'lazy' as const } })) || []
  },
  server: false
})

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' || status === 'idle'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>
Cet exemple utilise useLazyFetch avec server: false pour récupérer des données sur le client sans bloquer le rendu initial.L'état de chargement vérifie à la fois l'état pending et idle pour afficher un indicateur de chargement avant et pendant la récupération.

Avec filtre ignorer

Vous pouvez définir le champ ignoreFilter sur true sur un groupe pour désactiver la recherche interne et utiliser votre propre logique de recherche.

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

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

const { data: users, status } = useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users-search',
  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}`, loading: 'lazy' as const } })) || []
  },
  server: false
})

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' || status === 'idle'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { refDebounced } from '@vueuse/core'

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

const { data: users, status } = useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'command-palette-users-search',
  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}`, loading: 'lazy' as const } })) || []
  },
  server: false
})

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' || status === 'idle'"
    :groups="groups"
    class="flex-1 h-80"
  />
</template>
Cet exemple utilise refDebounced pour déboulonner les appels de l'API. L'état de chargement vérifie à la fois l'état pending et idle pour afficher un indicateur de chargement avant et pendant la récupération.

Avec éléments post-filtrés

Vous pouvez utiliser le champ postFilter sur un groupe pour filtrer les éléments après la recherche.

<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',
    label: 'Tailwind CSS',
    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>
Commencez à taper pour voir apparaître les éléments de niveau supérieur.

Avec recherche de fusible personnalisée

Vous pouvez utiliser la prop fuse pour remplacer les options de useFuse qui sont par défaut:

{
  fuseOptions: {
    ignoreLocation: true,
    threshold: 0.1,
    keys: ['label', 'description', 'suffix']
  },
  resultLimit: 12,
  matchAllWhenSearchEmpty: true
}
Les fuseOptions sont les options de Fuse.js, les resultLimit sont le nombre maximum de résultats à renvoyer et les matchAllWhenSearchEmpty sont un booléen pour faire correspondre tous les éléments lorsque le terme de recherche est vide.

Vous pouvez par exemple définir { fuseOptions: { includeMatches: true } } pour mettre en évidence le terme de recherche dans les éléments.

No data
<script setup lang="ts">
const { data: users } = useLazyFetch('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}`, loading: 'lazy' as const } })) || []
  },
  server: false
})
</script>

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

Avec virtualisation: badge{label="4.1+" class="align-text-top"}

Utilisez la prop virtualize pour activer la virtualisation de grandes listes en tant que booléen ou objet avec des options telles que { estimateSize: 32, overscan: 12 }.

Lorsqu 'il est activé, tous les groupes sont aplatis en une seule liste en raison d'une limitation de l'interface utilisateur de Reka.
<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>

Dans un Popover

Vous pouvez utiliser le composant CommandPalette dans le contenu d'un Popover.

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

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>
<script setup lang="ts">
import { ref } from 'vue'
import type { CommandPaletteItem } 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 CommandPaletteItem[])

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>

Dans un Modal

Vous pouvez utiliser le composant CommandPalette dans le contenu d'un Modal.

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

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'modal-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}`, loading: 'lazy' as const } })) || []
  },
  immediate: false
})

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

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

<template>
  <UModal @update:open="onOpen">
    <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>
<script setup lang="ts">
import { ref, computed } from 'vue'

const searchTerm = ref('')

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'modal-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}`, loading: 'lazy' as const } })) || []
  },
  immediate: false
})

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

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

<template>
  <UModal @update:open="onOpen">
    <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>
Cet exemple utilise useLazyFetch avec immediate: false pour récupérer des données uniquement lorsque le Modal s'ouvre.

Dans une armoire

Vous pouvez utiliser le composant CommandPalette dans le contenu d'un Drawer.

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

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'drawer-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}`, loading: 'lazy' as const } })) || []
  },
  immediate: false
})

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

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

<template>
  <UDrawer :handle="false" @update:open="onOpen">
    <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>
<script setup lang="ts">
import { ref, computed } from 'vue'

const searchTerm = ref('')

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'drawer-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}`, loading: 'lazy' as const } })) || []
  },
  immediate: false
})

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

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

<template>
  <UDrawer :handle="false" @update:open="onOpen">
    <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>
Cet exemple utilise useLazyFetch avec immediate: false pour récupérer des données uniquement lorsque le tiroir s'ouvre.

Listen ouvert

Lors de l'utilisation du prop close, vous pouvez écouter l'événement update:open lorsque vous cliquez sur le bouton.

<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',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Alex',
    suffix: 'hywax',
    to: 'https://github.com/hywax',
    target: '_blank',
    avatar: {
      src: 'https://github.com/hywax.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Maxime Pauvert',
    suffix: 'maximepvrt',
    to: 'https://github.com/maximepvrt',
    target: '_blank',
    avatar: {
      src: 'https://github.com/maximepvrt.png',
      loading: 'lazy' as const
    }
  }
]
</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>
<script setup lang="ts">
import { ref } from 'vue'

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',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Hugo Richard',
    suffix: 'HugoRCD',
    to: 'https://github.com/HugoRCD',
    target: '_blank',
    avatar: {
      src: 'https://github.com/HugoRCD.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sébastien Chopin',
    suffix: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Romain Hamel',
    suffix: 'romhml',
    to: 'https://github.com/romhml',
    target: '_blank',
    avatar: {
      src: 'https://github.com/romhml.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Sandro Circi',
    suffix: 'sandros94',
    to: 'https://github.com/sandros94',
    target: '_blank',
    avatar: {
      src: 'https://github.com/sandros94.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Jakub Michálek',
    suffix: 'J-Michalek',
    to: 'https://github.com/J-Michalek',
    target: '_blank',
    avatar: {
      src: 'https://github.com/J-Michalek.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Alex',
    suffix: 'hywax',
    to: 'https://github.com/hywax',
    target: '_blank',
    avatar: {
      src: 'https://github.com/hywax.png',
      loading: 'lazy' as const
    }
  },
  {
    label: 'Maxime Pauvert',
    suffix: 'maximepvrt',
    to: 'https://github.com/maximepvrt',
    target: '_blank',
    avatar: {
      src: 'https://github.com/maximepvrt.png',
      loading: 'lazy' as const
    }
  }
]
</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>
Cela peut être utile lorsque vous utilisez la CommandPalette à l'intérieur d'un Modal par exemple.

Avec slot de pied de page

Utilisez l'emplacement #footer pour ajouter du contenu personnalisé en bas de la palette de commandes, comme l'aide aux raccourcis clavier ou des actions supplémentaires.

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

With slot personnalisé

Utilisez la propriété slot pour personnaliser un élément ou un groupe spécifique.

Vous aurez accès aux slots suivants:

  • x#{{ item.slot }}x{lang="ts-type"}
  • x#{{ item.slot }}-leadingx{lang="ts-type"}
  • x#{{ item.slot }}-labelx{lang="ts-type"}
  • x#{{ item.slot }}-trailingx{lang="ts-type"}
  • x#{{ group.slot }}x{lang="ts-type"}
  • x#{{ group.slot }}-leadingx{lang="ts-type"}
  • x#{{ group.slot }}-labelx{lang="ts-type"}
  • x#{{ group.slot }}-trailingx{lang="ts-type"}
<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" loading="lazy" />
    </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>
Vous pouvez également utiliser les emplacements #item, #item-leading, #item-label et #item-trailing pour personnaliser tous les éléments.

API

Props and

Prop Default Type
as
'div'
any

The element or component this component should render as.

size
'md'
"sm" | "md" | "xs" | "lg" | "xl"
icon
appConfig.ui.icons.search
any

The icon displayed in the input. Set to false to hide the icon.

trailingIcon
appConfig.ui.icons.search
any

The icon displayed on the right side of the input.

selectedIcon
appConfig.ui.icons.check
any

The icon displayed when an item is selected.

childrenIcon
appConfig.ui.icons.chevronRight
any

The icon displayed when an item has children.

placeholder
t('commandPalette.placeholder')
string

The placeholder text for the input.

autofocus
true
boolean

Automatically focus the input when component is mounted.

close
false
boolean | Omit<ButtonProps, LinkPropsKeys>

Display a close button in the input (useful when inside a Modal for example). { size: 'md', color: 'neutral', variant: 'ghost' }

closeIcon
appConfig.ui.icons.close
any

The icon displayed in the close button.

back
true
boolean | Omit<ButtonProps, LinkPropsKeys>

Display a button to navigate back in history. { size: 'md', color: 'neutral', variant: 'link' }

backIcon
appConfig.ui.icons.arrowLeft
any

The icon displayed in the back button.

input
true
boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue">

Configure the input or hide it with false.

groups
G[]
fuse
{ fuseOptions: { ignoreLocation: true, threshold: 0.1, keys: ['label', 'description', 'suffix'] }, resultLimit: 12, matchAllWhenSearchEmpty: true }
UseFuseOptions<T>

Options for useFuse.

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

Enable virtualization for large lists. Note: when enabled, all groups are flattened into a single list due to a limitation of Reka UI (https://github.com/unovue/reka-ui/issues/1885).

valueKey
undefined
keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>

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

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

The key used to get the label from the item.

descriptionKey
'description'
keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>

The key used to get the description from the item.

preserveGroupOrder
false
boolean

Whether to preserve the order of groups as defined in the groups prop when filtering. When false, groups will appear based on item matches.

searchDelay
0
number

Delay (in milliseconds) before the search term is passed to Fuse (debounced). Useful when indexing large datasets where fuzzy search becomes the bottleneck — the input stays responsive while Fuse and the result pipeline only re-run after typing settles. Set to 0 (the default) to disable.

multiple
boolean

Whether multiple options can be selected or not.

disabled
boolean

When true, prevents the user from interacting with listbox

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

The controlled value of the listbox. Can be binded with v-model.

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

The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox

highlightOnHover
true
boolean

When true, hover over item will trigger highlight

selectionBehavior
'toggle'
"replace" | "toggle"

How multiple selection should behave in the collection.

by
string | (a: AcceptableValue, b: AcceptableValue): boolean

Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared.

loading
boolean

When true, the loading icon will be displayed.

loadingIcon
appConfig.ui.icons.loading
any

The icon when the loading prop is true.

searchTerm
''
string
ui
{ root?: SlotClass; input?: SlotClass; close?: SlotClass; back?: SlotClass; content?: SlotClass; footer?: SlotClass; viewport?: SlotClass; group?: SlotClass; empty?: SlotClass; label?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemLeadingChip?: SlotClass; itemLeadingChipSize?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; itemTrailingHighlightedIcon?: SlotClass; itemTrailingKbds?: SlotClass; itemTrailingKbdsSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemLabelBase?: SlotClass; itemLabelPrefix?: SlotClass; itemLabelSuffix?: SlotClass; itemDescription?: SlotClass; }

Slots

Slot Type
empty
{ searchTerm: string; }
footer
{ ui: object; }
back
{ ui: object; }
close
{ ui: object; }
item
{ item: T; index: number; ui: object; }
item-leading
{ item: T; index: number; ui: object; }
item-label
{ item: T; index: number; ui: object; }
item-description
{ item: T; index: number; ui: object; }
item-trailing
{ item: T; index: number; ui: object; }
group-label
{ group: G; label: string; ui: object; }

Emis

Event Type
update:modelValue
[value: T]
highlight
[payload: { ref: HTMLElement; value: T; } | undefined]
entryFocus
[event: CustomEvent<any>]
leave
[event: Event]
update:open
[value: boolean]
update:searchTerm
[value: string]

Thème

app.config.ts
export default defineAppConfig({
  ui: {
    commandPalette: {
      slots: {
        root: 'flex flex-col min-h-0 min-w-0 divide-y divide-default',
        input: '',
        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: 'text-center text-muted',
        label: 'font-semibold text-highlighted',
        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',
        itemLeadingIcon: 'shrink-0',
        itemLeadingAvatar: 'shrink-0',
        itemLeadingAvatarSize: '',
        itemLeadingChip: 'shrink-0',
        itemLeadingChipSize: '',
        itemTrailing: 'ms-auto inline-flex items-center',
        itemTrailingIcon: 'shrink-0',
        itemTrailingHighlightedIcon: 'shrink-0 text-dimmed hidden group-data-highlighted:inline-flex',
        itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
        itemTrailingKbdsSize: '',
        itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
        itemLabel: 'truncate space-x-1 text-dimmed',
        itemLabelBase: 'text-highlighted [&>mark]:text-primary [&>mark]:bg-primary/15',
        itemLabelPrefix: 'text-default',
        itemLabelSuffix: 'text-dimmed [&>mark]:text-primary [&>mark]:bg-primary/15',
        itemDescription: 'truncate text-muted [&>mark]:text-primary [&>mark]:bg-primary/15'
      },
      variants: {
        virtualize: {
          true: {
            viewport: 'p-1 isolate'
          },
          false: {
            viewport: 'divide-y divide-default'
          }
        },
        size: {
          xs: {
            input: '[&>input]:h-10',
            empty: 'py-3 text-xs',
            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',
            itemTrailing: 'gap-1',
            itemTrailingIcon: 'size-4',
            itemTrailingHighlightedIcon: 'size-4',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'sm'
          },
          sm: {
            input: '[&>input]:h-11',
            empty: 'py-4 text-xs',
            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',
            itemTrailing: 'gap-1.5',
            itemTrailingIcon: 'size-4',
            itemTrailingHighlightedIcon: 'size-4',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'sm'
          },
          md: {
            input: '[&>input]:h-12',
            empty: 'py-6 text-sm',
            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',
            itemTrailing: 'gap-1.5',
            itemTrailingIcon: 'size-5',
            itemTrailingHighlightedIcon: 'size-5',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'md'
          },
          lg: {
            input: '[&>input]:h-13',
            empty: 'py-7 text-sm',
            label: 'p-2 text-xs gap-2',
            item: 'p-2 text-sm gap-2',
            itemLeadingIcon: 'size-5',
            itemLeadingAvatarSize: '2xs',
            itemLeadingChip: 'size-5',
            itemLeadingChipSize: 'md',
            itemTrailing: 'gap-2',
            itemTrailingIcon: 'size-5',
            itemTrailingHighlightedIcon: 'size-5',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'md'
          },
          xl: {
            input: '[&>input]:h-14',
            empty: 'py-8 text-base',
            label: 'p-2 text-sm gap-2',
            item: 'p-2 text-base gap-2',
            itemLeadingIcon: 'size-6',
            itemLeadingAvatarSize: 'xs',
            itemLeadingChip: 'size-6',
            itemLeadingChipSize: 'lg',
            itemTrailing: 'gap-2',
            itemTrailingIcon: 'size-6',
            itemTrailingHighlightedIcon: 'size-6',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'lg'
          }
        },
        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'
          }
        }
      },
      defaultVariants: {
        size: 'md'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        commandPalette: {
          slots: {
            root: 'flex flex-col min-h-0 min-w-0 divide-y divide-default',
            input: '',
            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: 'text-center text-muted',
            label: 'font-semibold text-highlighted',
            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',
            itemLeadingIcon: 'shrink-0',
            itemLeadingAvatar: 'shrink-0',
            itemLeadingAvatarSize: '',
            itemLeadingChip: 'shrink-0',
            itemLeadingChipSize: '',
            itemTrailing: 'ms-auto inline-flex items-center',
            itemTrailingIcon: 'shrink-0',
            itemTrailingHighlightedIcon: 'shrink-0 text-dimmed hidden group-data-highlighted:inline-flex',
            itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
            itemTrailingKbdsSize: '',
            itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
            itemLabel: 'truncate space-x-1 text-dimmed',
            itemLabelBase: 'text-highlighted [&>mark]:text-primary [&>mark]:bg-primary/15',
            itemLabelPrefix: 'text-default',
            itemLabelSuffix: 'text-dimmed [&>mark]:text-primary [&>mark]:bg-primary/15',
            itemDescription: 'truncate text-muted [&>mark]:text-primary [&>mark]:bg-primary/15'
          },
          variants: {
            virtualize: {
              true: {
                viewport: 'p-1 isolate'
              },
              false: {
                viewport: 'divide-y divide-default'
              }
            },
            size: {
              xs: {
                input: '[&>input]:h-10',
                empty: 'py-3 text-xs',
                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',
                itemTrailing: 'gap-1',
                itemTrailingIcon: 'size-4',
                itemTrailingHighlightedIcon: 'size-4',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'sm'
              },
              sm: {
                input: '[&>input]:h-11',
                empty: 'py-4 text-xs',
                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',
                itemTrailing: 'gap-1.5',
                itemTrailingIcon: 'size-4',
                itemTrailingHighlightedIcon: 'size-4',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'sm'
              },
              md: {
                input: '[&>input]:h-12',
                empty: 'py-6 text-sm',
                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',
                itemTrailing: 'gap-1.5',
                itemTrailingIcon: 'size-5',
                itemTrailingHighlightedIcon: 'size-5',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'md'
              },
              lg: {
                input: '[&>input]:h-13',
                empty: 'py-7 text-sm',
                label: 'p-2 text-xs gap-2',
                item: 'p-2 text-sm gap-2',
                itemLeadingIcon: 'size-5',
                itemLeadingAvatarSize: '2xs',
                itemLeadingChip: 'size-5',
                itemLeadingChipSize: 'md',
                itemTrailing: 'gap-2',
                itemTrailingIcon: 'size-5',
                itemTrailingHighlightedIcon: 'size-5',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'md'
              },
              xl: {
                input: '[&>input]:h-14',
                empty: 'py-8 text-base',
                label: 'p-2 text-sm gap-2',
                item: 'p-2 text-base gap-2',
                itemLeadingIcon: 'size-6',
                itemLeadingAvatarSize: 'xs',
                itemLeadingChip: 'size-6',
                itemLeadingChipSize: 'lg',
                itemTrailing: 'gap-2',
                itemTrailingIcon: 'size-6',
                itemTrailingHighlightedIcon: 'size-6',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'lg'
              }
            },
            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'
              }
            }
          },
          defaultVariants: {
            size: 'md'
          }
        }
      }
    })
  ]
})

Changelog écrit

No recent changes