dropdownmenu

Un menu pour afficher les actions lorsque vous cliquez sur un élément.

Utilisation

Utilisez un Button ou tout autre composant dans l'emplacement par défaut du menu déroulant.

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

const items = ref<DropdownMenuItem[][]>([
  [
    {
      label: 'Benjamin',
      avatar: {
        src: 'https://github.com/benjamincanac.png',
        loading: 'lazy'
      },
      type: 'label'
    }
  ],
  [
    {
      label: 'Profile',
      icon: 'i-lucide-user'
    },
    {
      label: 'Billing',
      icon: 'i-lucide-credit-card'
    },
    {
      label: 'Settings',
      icon: 'i-lucide-cog',
      kbds: [',']
    },
    {
      label: 'Keyboard shortcuts',
      icon: 'i-lucide-monitor'
    }
  ],
  [
    {
      label: 'Team',
      icon: 'i-lucide-users',
      filter: {
        placeholder: 'Search members...'
      },
      children: [
        [
          {
            label: 'benjamincanac',
            avatar: {
              src: 'https://github.com/benjamincanac.png',
              loading: 'lazy'
            }
          },
          {
            label: 'HugoRCD',
            avatar: {
              src: 'https://github.com/HugoRCD.png',
              loading: 'lazy'
            }
          },
          {
            label: 'atinux',
            avatar: {
              src: 'https://github.com/atinux.png',
              loading: 'lazy'
            }
          },
          {
            label: 'romhml',
            avatar: {
              src: 'https://github.com/romhml.png',
              loading: 'lazy'
            }
          },
          {
            label: 'sandros94',
            avatar: {
              src: 'https://github.com/sandros94.png',
              loading: 'lazy'
            }
          },
          {
            label: 'J-Michalek',
            avatar: {
              src: 'https://github.com/J-Michalek.png',
              loading: 'lazy'
            }
          },
          {
            label: 'hywax',
            avatar: {
              src: 'https://github.com/hywax.png',
              loading: 'lazy'
            }
          }
        ]
      ]
    },
    {
      label: 'Invite users',
      icon: 'i-lucide-user-plus',
      children: [
        [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Message',
            icon: 'i-lucide-message-square'
          }
        ],
        [
          {
            label: 'More',
            icon: 'i-lucide-circle-plus',
            children: [
              {
                label: 'Import from Slack',
                icon: 'i-simple-icons-slack',
                to: 'https://slack.com',
                target: '_blank'
              },
              {
                label: 'Import from Trello',
                icon: 'i-simple-icons-trello'
              },
              {
                label: 'Import from Asana',
                icon: 'i-simple-icons-asana'
              }
            ]
          }
        ]
      ]
    },
    {
      label: 'New team',
      icon: 'i-lucide-plus',
      kbds: ['meta', 'n']
    }
  ],
  [
    {
      label: 'GitHub',
      icon: 'i-simple-icons-github',
      to: 'https://github.com/nuxt/ui',
      target: '_blank'
    },
    {
      label: 'Support',
      icon: 'i-lucide-life-buoy',
      to: '/docs/components/dropdown-menu'
    },
    {
      label: 'API',
      icon: 'i-lucide-cloud',
      disabled: true
    }
  ],
  [
    {
      label: 'Logout',
      icon: 'i-lucide-log-out',
      color: 'error',
      kbds: ['shift', 'meta', 'q']
    }
  ]
])
</script>

<template>
  <UDropdownMenu :items="items">
    <UButton icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[][]>([
  [
    {
      label: 'Benjamin',
      avatar: {
        src: 'https://github.com/benjamincanac.png',
        loading: 'lazy'
      },
      type: 'label'
    }
  ],
  [
    {
      label: 'Profile',
      icon: 'i-lucide-user'
    },
    {
      label: 'Billing',
      icon: 'i-lucide-credit-card'
    },
    {
      label: 'Settings',
      icon: 'i-lucide-cog',
      kbds: [',']
    },
    {
      label: 'Keyboard shortcuts',
      icon: 'i-lucide-monitor'
    }
  ],
  [
    {
      label: 'Team',
      icon: 'i-lucide-users',
      filter: {
        placeholder: 'Search members...'
      },
      children: [
        [
          {
            label: 'benjamincanac',
            avatar: {
              src: 'https://github.com/benjamincanac.png',
              loading: 'lazy'
            }
          },
          {
            label: 'HugoRCD',
            avatar: {
              src: 'https://github.com/HugoRCD.png',
              loading: 'lazy'
            }
          },
          {
            label: 'atinux',
            avatar: {
              src: 'https://github.com/atinux.png',
              loading: 'lazy'
            }
          },
          {
            label: 'romhml',
            avatar: {
              src: 'https://github.com/romhml.png',
              loading: 'lazy'
            }
          },
          {
            label: 'sandros94',
            avatar: {
              src: 'https://github.com/sandros94.png',
              loading: 'lazy'
            }
          },
          {
            label: 'J-Michalek',
            avatar: {
              src: 'https://github.com/J-Michalek.png',
              loading: 'lazy'
            }
          },
          {
            label: 'hywax',
            avatar: {
              src: 'https://github.com/hywax.png',
              loading: 'lazy'
            }
          }
        ]
      ]
    },
    {
      label: 'Invite users',
      icon: 'i-lucide-user-plus',
      children: [
        [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Message',
            icon: 'i-lucide-message-square'
          }
        ],
        [
          {
            label: 'More',
            icon: 'i-lucide-circle-plus',
            children: [
              {
                label: 'Import from Slack',
                icon: 'i-simple-icons-slack',
                to: 'https://slack.com',
                target: '_blank'
              },
              {
                label: 'Import from Trello',
                icon: 'i-simple-icons-trello'
              },
              {
                label: 'Import from Asana',
                icon: 'i-simple-icons-asana'
              }
            ]
          }
        ]
      ]
    },
    {
      label: 'New team',
      icon: 'i-lucide-plus',
      kbds: ['meta', 'n']
    }
  ],
  [
    {
      label: 'GitHub',
      icon: 'i-simple-icons-github',
      to: 'https://github.com/nuxt/ui',
      target: '_blank'
    },
    {
      label: 'Support',
      icon: 'i-lucide-life-buoy',
      to: '/docs/components/dropdown-menu'
    },
    {
      label: 'API',
      icon: 'i-lucide-cloud',
      disabled: true
    }
  ],
  [
    {
      label: 'Logout',
      icon: 'i-lucide-log-out',
      color: 'error',
      kbds: ['shift', 'meta', 'q']
    }
  ]
])
</script>

<template>
  <UDropdownMenu :items="items">
    <UButton icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>

Articles

Utilisez le prop items comme un tableau d'objets avec les propriétés suivantes:

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

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

const items = ref<DropdownMenuItem[][]>([
  [
    {
      label: 'Benjamin',
      avatar: {
        src: 'https://github.com/benjamincanac.png',
        loading: 'lazy'
      },
      type: 'label'
    }
  ],
  [
    {
      label: 'Profile',
      icon: 'i-lucide-user'
    },
    {
      label: 'Billing',
      icon: 'i-lucide-credit-card'
    },
    {
      label: 'Settings',
      icon: 'i-lucide-cog',
      kbds: [',']
    },
    {
      label: 'Keyboard shortcuts',
      icon: 'i-lucide-monitor'
    }
  ],
  [
    {
      label: 'Team',
      icon: 'i-lucide-users'
    },
    {
      label: 'Invite users',
      icon: 'i-lucide-user-plus',
      children: [
        [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Message',
            icon: 'i-lucide-message-square'
          }
        ],
        [
          {
            label: 'More',
            icon: 'i-lucide-circle-plus',
            children: [
              {
                label: 'Import from Slack',
                icon: 'i-simple-icons-slack',
                to: 'https://slack.com',
                target: '_blank'
              },
              {
                label: 'Import from Trello',
                icon: 'i-simple-icons-trello'
              },
              {
                label: 'Import from Asana',
                icon: 'i-simple-icons-asana'
              }
            ]
          }
        ]
      ]
    },
    {
      label: 'New team',
      icon: 'i-lucide-plus',
      kbds: ['meta', 'n']
    }
  ],
  [
    {
      label: 'GitHub',
      icon: 'i-simple-icons-github',
      to: 'https://github.com/nuxt/ui',
      target: '_blank'
    },
    {
      label: 'Support',
      icon: 'i-lucide-life-buoy',
      to: '/docs/components/dropdown-menu'
    },
    {
      label: 'API',
      icon: 'i-lucide-cloud',
      disabled: true
    }
  ],
  [
    {
      label: 'Logout',
      icon: 'i-lucide-log-out',
      kbds: ['shift', 'meta', 'q']
    }
  ]
])
</script>

<template>
  <UDropdownMenu
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[][]>([
  [
    {
      label: 'Benjamin',
      avatar: {
        src: 'https://github.com/benjamincanac.png',
        loading: 'lazy'
      },
      type: 'label'
    }
  ],
  [
    {
      label: 'Profile',
      icon: 'i-lucide-user'
    },
    {
      label: 'Billing',
      icon: 'i-lucide-credit-card'
    },
    {
      label: 'Settings',
      icon: 'i-lucide-cog',
      kbds: [',']
    },
    {
      label: 'Keyboard shortcuts',
      icon: 'i-lucide-monitor'
    }
  ],
  [
    {
      label: 'Team',
      icon: 'i-lucide-users'
    },
    {
      label: 'Invite users',
      icon: 'i-lucide-user-plus',
      children: [
        [
          {
            label: 'Email',
            icon: 'i-lucide-mail'
          },
          {
            label: 'Message',
            icon: 'i-lucide-message-square'
          }
        ],
        [
          {
            label: 'More',
            icon: 'i-lucide-circle-plus',
            children: [
              {
                label: 'Import from Slack',
                icon: 'i-simple-icons-slack',
                to: 'https://slack.com',
                target: '_blank'
              },
              {
                label: 'Import from Trello',
                icon: 'i-simple-icons-trello'
              },
              {
                label: 'Import from Asana',
                icon: 'i-simple-icons-asana'
              }
            ]
          }
        ]
      ]
    },
    {
      label: 'New team',
      icon: 'i-lucide-plus',
      kbds: ['meta', 'n']
    }
  ],
  [
    {
      label: 'GitHub',
      icon: 'i-simple-icons-github',
      to: 'https://github.com/nuxt/ui',
      target: '_blank'
    },
    {
      label: 'Support',
      icon: 'i-lucide-life-buoy',
      to: '/docs/components/dropdown-menu'
    },
    {
      label: 'API',
      icon: 'i-lucide-cloud',
      disabled: true
    }
  ],
  [
    {
      label: 'Logout',
      icon: 'i-lucide-log-out',
      kbds: ['shift', 'meta', 'q']
    }
  ]
])
</script>

<template>
  <UDropdownMenu
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
Vous pouvez également passer un tableau de tableaux à la prop items pour créer des groupes d'éléments séparés.
Chaque élément peut prendre un tableau d'objets children avec les mêmes propriétés que le prop items pour créer un menu imbriqué qui peut être contrôlé à l'aide des propriétés open, defaultOpen et content.

contenu

Utilisez la prop content pour contrôler la façon dont le contenu du menu déroulant est rendu, comme son align ou side par exemple.

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    :items="items"
    :content="{
      align: 'start',
      side: 'bottom',
      sideOffset: 8
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    :items="items"
    :content="{
      align: 'start',
      side: 'bottom',
      sideOffset: 8
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>

Filter: badge{label="4.6+" class="align-text-top"}

Utilisez la prop filter pour afficher une entrée de filtre à l'intérieur du menu déroulant.

Utilisez le prop ignore-filter pour désactiver la recherche interne et utiliser votre propre logique de recherche.
Utilisez la prop filter-fields pour spécifier les champs à filtrer. Par défaut, il utilise la prop labelKey.

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

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  },
  {
    label: 'Team',
    icon: 'i-lucide-users'
  },
  {
    label: 'Invite users',
    icon: 'i-lucide-user-plus'
  },
  {
    label: 'New team',
    icon: 'i-lucide-plus'
  }
])
</script>

<template>
  <UDropdownMenu
    :filter="{
      icon: 'i-lucide-search'
    }"
    :items="items"
    :content="{
      align: 'start'
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  },
  {
    label: 'Team',
    icon: 'i-lucide-users'
  },
  {
    label: 'Invite users',
    icon: 'i-lucide-user-plus'
  },
  {
    label: 'New team',
    icon: 'i-lucide-plus'
  }
])
</script>

<template>
  <UDropdownMenu
    :filter="{
      icon: 'i-lucide-search'
    }"
    :items="items"
    :content="{
      align: 'start'
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
Vous pouvez également activer le filtre sur des sous-menus spécifiques en utilisant le champ filter sur les éléments avec children.

Arrow équipé

Utilisez la prop arrow pour afficher une flèche dans le menu déroulant.

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    arrow
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    arrow
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>

Size

Utilisez le prop size pour contrôler la taille du menu déroulant.

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    size="xl"
    :items="items"
    :content="{
      align: 'start'
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton size="xl" label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    size="xl"
    :items="items"
    :content="{
      align: 'start'
    }"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton size="xl" label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
Le prop size ne sera pas associé au bouton, vous devez le configurer vous-même.
En utilisant la même taille, les éléments du menu déroulant seront parfaitement alignés avec le bouton.

Modale

Utilisez la prop modal pour contrôler si le menu déroulant bloque l'interaction avec le contenu extérieur.

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    :modal="false"
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    :modal="false"
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>

Désactivé

Utilisez la prop disabled pour désactiver le menu déroulant.

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

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    disabled
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const items = ref<DropdownMenuItem[]>([
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  },
  {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  },
  {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
])
</script>

<template>
  <UDropdownMenu
    disabled
    :items="items"
    :ui="{
      content: 'w-48'
    }"
  >
    <UButton label="Open" icon="i-lucide-menu" color="neutral" variant="outline" />
  </UDropdownMenu>
</template>

Exemples

With checkbox éléments

Vous pouvez utiliser la propriété type avec checkbox et utiliser les propriétés checked/onUpdateChecked pour contrôler l'état vérifié de l'élément.

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

const showBookmarks = ref(true)
const showHistory = ref(false)
const showDownloads = ref(false)

const items = computed(() => [{
  label: 'Interface',
  icon: 'i-lucide-app-window',
  type: 'label' as const
}, {
  type: 'separator' as const
}, {
  label: 'Show Bookmarks',
  icon: 'i-lucide-bookmark',
  type: 'checkbox' as const,
  checked: showBookmarks.value,
  onUpdateChecked(checked: boolean) {
    showBookmarks.value = checked
  },
  onSelect(e: Event) {
    e.preventDefault()
  }
}, {
  label: 'Show History',
  icon: 'i-lucide-clock',
  type: 'checkbox' as const,
  checked: showHistory.value,
  onUpdateChecked(checked: boolean) {
    showHistory.value = checked
  }
}, {
  label: 'Show Downloads',
  icon: 'i-lucide-download',
  type: 'checkbox' as const,
  checked: showDownloads.value,
  onUpdateChecked(checked: boolean) {
    showDownloads.value = checked
  }
}] satisfies DropdownMenuItem[])
</script>

<template>
  <UDropdownMenu :items="items" :content="{ align: 'start' }" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const showBookmarks = ref(true)
const showHistory = ref(false)
const showDownloads = ref(false)

const items = computed(() => [{
  label: 'Interface',
  icon: 'i-lucide-app-window',
  type: 'label' as const
}, {
  type: 'separator' as const
}, {
  label: 'Show Bookmarks',
  icon: 'i-lucide-bookmark',
  type: 'checkbox' as const,
  checked: showBookmarks.value,
  onUpdateChecked(checked: boolean) {
    showBookmarks.value = checked
  },
  onSelect(e: Event) {
    e.preventDefault()
  }
}, {
  label: 'Show History',
  icon: 'i-lucide-clock',
  type: 'checkbox' as const,
  checked: showHistory.value,
  onUpdateChecked(checked: boolean) {
    showHistory.value = checked
  }
}, {
  label: 'Show Downloads',
  icon: 'i-lucide-download',
  type: 'checkbox' as const,
  checked: showDownloads.value,
  onUpdateChecked(checked: boolean) {
    showDownloads.value = checked
  }
}] satisfies DropdownMenuItem[])
</script>

<template>
  <UDropdownMenu :items="items" :content="{ align: 'start' }" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
Pour assurer la réactivité de l'état des éléments checked, il est recommandé d'envelopper votre tableau items dans un computed.

Avec éléments de couleur

Vous pouvez utiliser la propriété color pour mettre en évidence certains éléments avec une couleur.

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

const items: DropdownMenuItem[][] = [
  [
    {
      label: 'View',
      icon: 'i-lucide-eye'
    },
    {
      label: 'Copy',
      icon: 'i-lucide-copy'
    },
    {
      label: 'Edit',
      icon: 'i-lucide-pencil'
    }
  ],
  [
    {
      label: 'Delete',
      color: 'error',
      icon: 'i-lucide-trash'
    }
  ]
]
</script>

<template>
  <UDropdownMenu :items="items" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>

Avec éléments de filtre: badge{label="4.6+" class="align-text-top"}

Vous pouvez utiliser la propriété filter sur les éléments avec children pour afficher une entrée de filtre dans le sous-menu.

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

const items: DropdownMenuItem[][] = [[{
  label: 'Profile',
  icon: 'i-lucide-user'
}, {
  label: 'Billing',
  icon: 'i-lucide-credit-card'
}, {
  label: 'Settings',
  icon: 'i-lucide-cog'
}], [{
  label: 'Team',
  icon: 'i-lucide-users',
  filter: {
    placeholder: 'Search members...'
  },
  children: [
    {
      label: 'benjamincanac',
      avatar: { src: 'https://github.com/benjamincanac.png', loading: 'lazy' as const }
    },
    {
      label: 'HugoRCD',
      avatar: { src: 'https://github.com/HugoRCD.png', loading: 'lazy' as const }
    },
    {
      label: 'atinux',
      avatar: { src: 'https://github.com/atinux.png', loading: 'lazy' as const }
    },
    {
      label: 'romhml',
      avatar: { src: 'https://github.com/romhml.png', loading: 'lazy' as const }
    },
    {
      label: 'sandros94',
      avatar: { src: 'https://github.com/sandros94.png', loading: 'lazy' as const }
    },
    {
      label: 'J-Michalek',
      avatar: { src: 'https://github.com/J-Michalek.png', loading: 'lazy' as const }
    },
    {
      label: 'hywax',
      avatar: { src: 'https://github.com/hywax.png', loading: 'lazy' as const }
    }
  ]
}, {
  label: 'Invite users',
  icon: 'i-lucide-user-plus',
  children: [{
    label: 'Invite by email',
    icon: 'i-lucide-mail'
  }, {
    label: 'Invite by link',
    icon: 'i-lucide-link'
  }, {
    label: 'Invite by SMS',
    icon: 'i-lucide-message-square'
  }, {
    label: 'Invite by WhatsApp',
    icon: 'i-simple-icons-whatsapp'
  }]
}, {
  label: 'New team',
  icon: 'i-lucide-plus'
}]]
</script>

<template>
  <UDropdownMenu :items="items" :content="{ align: 'start' }" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>

Control État ouvert

Vous pouvez contrôler l'état ouvert en utilisant la prop default-open ou la directive v-model:open.

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

const open = ref(false)

defineShortcuts({
  o: () => open.value = !open.value
})

const items: DropdownMenuItem[] = [
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  }, {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  }, {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
]
</script>

<template>
  <UDropdownMenu v-model:open="open" :items="items" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const open = ref(false)

defineShortcuts({
  o: () => open.value = !open.value
})

const items: DropdownMenuItem[] = [
  {
    label: 'Profile',
    icon: 'i-lucide-user'
  }, {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  }, {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
]
</script>

<template>
  <UDropdownMenu v-model:open="open" :items="items" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
Dans cet exemple, en utilisant defineShortcuts, vous pouvez basculer le menu déroulant en appuyant sur: kbd{value="O"}.

With slot personnalisé

Utilisez la propriété slot pour personnaliser un élément 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"}
<script setup lang="ts">
import type { DropdownMenuItem } from '@nuxt/ui'

const items = [
  {
    label: 'Profile',
    icon: 'i-lucide-user',
    slot: 'profile' as const
  }, {
    label: 'Billing',
    icon: 'i-lucide-credit-card'
  }, {
    label: 'Settings',
    icon: 'i-lucide-cog'
  }
] satisfies DropdownMenuItem[]
</script>

<template>
  <UDropdownMenu :items="items" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />

    <template #profile-trailing>
      <UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-primary" />
    </template>
  </UDropdownMenu>
</template>
Vous pouvez également utiliser les emplacements #item, #item-leading, #item-label et #item-trailing pour personnaliser tous les éléments.

With Switch dans les articles

Vous pouvez utiliser la propriété slot avec un emplacement #{{ slot }}-trailing pour rendre un Switch à l'intérieur d'un élément.

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

const showBookmarks = ref(true)
const showHistory = ref(false)
const showDownloads = ref(false)

const items = computed(() => [{
  label: 'Show Bookmarks',
  icon: 'i-lucide-bookmark',
  slot: 'switch' as const,
  checked: showBookmarks.value,
  onSelect(e: Event) {
    e.preventDefault()
    showBookmarks.value = !showBookmarks.value
  }
}, {
  label: 'Show History',
  icon: 'i-lucide-clock',
  slot: 'switch' as const,
  checked: showHistory.value,
  onSelect(e: Event) {
    e.preventDefault()
    showHistory.value = !showHistory.value
  }
}, {
  label: 'Show Downloads',
  icon: 'i-lucide-download',
  slot: 'switch' as const,
  checked: showDownloads.value,
  onSelect(e: Event) {
    e.preventDefault()
    showDownloads.value = !showDownloads.value
  }
}] satisfies DropdownMenuItem[])
</script>

<template>
  <UDropdownMenu :items="items" :content="{ align: 'start' }" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />

    <template #switch-trailing="{ item }">
      <USwitch :model-value="item.checked" tabindex="-1" />
    </template>
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { DropdownMenuItem } from '@nuxt/ui'

const showBookmarks = ref(true)
const showHistory = ref(false)
const showDownloads = ref(false)

const items = computed(() => [{
  label: 'Show Bookmarks',
  icon: 'i-lucide-bookmark',
  slot: 'switch' as const,
  checked: showBookmarks.value,
  onSelect(e: Event) {
    e.preventDefault()
    showBookmarks.value = !showBookmarks.value
  }
}, {
  label: 'Show History',
  icon: 'i-lucide-clock',
  slot: 'switch' as const,
  checked: showHistory.value,
  onSelect(e: Event) {
    e.preventDefault()
    showHistory.value = !showHistory.value
  }
}, {
  label: 'Show Downloads',
  icon: 'i-lucide-download',
  slot: 'switch' as const,
  checked: showDownloads.value,
  onSelect(e: Event) {
    e.preventDefault()
    showDownloads.value = !showDownloads.value
  }
}] satisfies DropdownMenuItem[])
</script>

<template>
  <UDropdownMenu :items="items" :content="{ align: 'start' }" :ui="{ content: 'w-48' }">
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />

    <template #switch-trailing="{ item }">
      <USwitch :model-value="item.checked" tabindex="-1" />
    </template>
  </UDropdownMenu>
</template>

Avec ignorer le filtre: badge{label="4.6+" class="align-text-top"}

Lorsque vous utilisez la prop filter ou le champ filter sur des éléments avec children, vous pouvez définir la prop ignore-filter sur true pour désactiver la recherche interne et utiliser votre propre logique de recherche.

<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { DropdownMenuItem } from '@nuxt/ui'

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

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'dropdown-menu-users-search',
  params: { q: searchTermDebounced },
  transform: (data: { id: number, name: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    })) as DropdownMenuItem[]
  },
  immediate: false
})

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

<template>
  <UDropdownMenu
    v-model:search-term="searchTerm"
    :items="users || []"
    :filter="{
      icon: 'i-lucide-search',
      loading: status === 'pending'
    }"
    ignore-filter
    :content="{ align: 'start' }"
    :ui="{ content: 'w-48' }"
    @update:open="onOpen"
  >
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { refDebounced } from '@vueuse/core'
import type { DropdownMenuItem } from '@nuxt/ui'

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

const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
  key: 'dropdown-menu-users-search',
  params: { q: searchTermDebounced },
  transform: (data: { id: number, name: string }[]) => {
    return data?.map(user => ({
      label: user.name,
      avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
    })) as DropdownMenuItem[]
  },
  immediate: false
})

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

<template>
  <UDropdownMenu
    v-model:search-term="searchTerm"
    :items="users || []"
    :filter="{
      icon: 'i-lucide-search',
      loading: status === 'pending'
    }"
    ignore-filter
    :content="{ align: 'start' }"
    :ui="{ content: 'w-48' }"
    @update:open="onOpen"
  >
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>
Cet exemple utilise refDebounced pour déboulonner les appels de l'API. La récupération est différée avec immediate: false afin qu 'aucune demande ne soit faite jusqu'à ce que le menu s'ouvre.

Avec les champs de filtre: badge{label="4.6+" class="align-text-top"}

Lorsque vous utilisez la prop filter ou le champ filter sur des éléments avec children, vous pouvez définir la prop filter-fields avec un tableau de champs à filtrer.

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

const items: DropdownMenuItem[] = [{
  label: 'Leanne Graham',
  description: 'Sincere@april.biz'
}, {
  label: 'Ervin Howell',
  description: 'Shanna@melissa.tv'
}, {
  label: 'Clementine Bauch',
  description: 'Nathan@yesenia.net'
}, {
  label: 'Patricia Lebsack',
  description: 'Julianne.OConner@kory.org'
}, {
  label: 'Chelsey Dietrich',
  description: 'Lucio_Hettinger@annie.me'
}]
</script>

<template>
  <UDropdownMenu
    :items="items"
    filter
    :filter-fields="['label', 'description']"
    :content="{ align: 'start' }"
    :ui="{ content: 'w-64' }"
  >
    <UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
  </UDropdownMenu>
</template>

Avec largeur de contenu de déclenchement

Vous pouvez développer le contenu sur toute la largeur de son bouton en ajoutant la classe w-(--reka-dropdown-menu-trigger-width) sur l'emplacement ui.content.

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

const items: DropdownMenuItem[][] = [
  [
    {
      label: 'View',
      icon: 'i-lucide-eye'
    },
    {
      label: 'Copy',
      icon: 'i-lucide-copy'
    },
    {
      label: 'Edit',
      icon: 'i-lucide-pencil'
    }
  ],
  [
    {
      label: 'Delete',
      color: 'error',
      icon: 'i-lucide-trash'
    }
  ]
]
</script>

<template>
  <UDropdownMenu :items="items" :ui="{ content: 'w-(--reka-dropdown-menu-trigger-width)' }">
    <UButton
      label="Open"
      class="w-46"
      color="neutral"
      variant="outline"
      block
      trailing-icon="i-lucide-chevron-down"
    />
  </UDropdownMenu>
</template>
Vous pouvez également modifier la largeur du contenu globalement dans votre app.config.ts:
export default defineAppConfig({
  ui: {
    dropdownMenu: {
      slots: {
        content: 'w-(--reka-dropdown-menu-trigger-width)'
      }
    }
  }
})

Extract raccourcis

Utilisez l'utilitaire extractShortcuts pour définir automatiquement des raccourcis à partir d'éléments de menu avec une propriété kbds. Il extrait récursivement des raccourcis et renvoie un objet compatible avec defineShortcuts.

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

const items: DropdownMenuItem[] = [{
  label: 'Invite users',
  icon: 'i-lucide-user-plus',
  children: [{
    label: 'Invite by email',
    icon: 'i-lucide-send-horizontal',
    kbds: ['meta', 'e'],
    onSelect() {
      console.log('Invite by email clicked')
    }
  }, {
    label: 'Invite by link',
    icon: 'i-lucide-link',
    kbds: ['meta', 'i'],
    onSelect() {
      console.log('Invite by link clicked')
    }
  }]
}, {
  label: 'New team',
  icon: 'i-lucide-plus',
  kbds: ['meta', 'n'],
  onSelect() {
    console.log('New team clicked')
  }
}]

defineShortcuts(extractShortcuts(items))
</script>
Dans cet exemple,: kbd{value="meta"}: kbd{value="E" class="ms-px"},: kbd{value="meta"}: kbd{value="I" class="ms-px"} et: kbd{value="meta"}: kbd{value="N" class="ms-px"} déclencheraient la fonction select de l'élément correspondant.

API and

Props équipements

Prop Default Type
size
'md'
"sm" | "md" | "xs" | "lg" | "xl"
items
T
checkedIcon
appConfig.ui.icons.check
any

The icon displayed when an item is checked.

loadingIcon
appConfig.ui.icons.loading
any

The icon displayed when an item is loading.

externalIcon
true
any

The icon displayed when the item is an external link. Set to false to hide the external icon.

content
{ side: 'bottom', sideOffset: 8, collisionPadding: 8 }
DropdownMenuContentProps & Partial<EmitsToProps<MenuContentEmits>>

The content of the menu.

arrow
false
boolean | DropdownMenuArrowProps

Display an arrow alongside the menu. { rounded: true }

portal
true
string | false | true | HTMLElement

Render the menu in a portal.

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.

filter
false
boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue">

Whether to display a filter input or not. Can be an object to pass additional props to the input. { placeholder: 'Search...', variant: 'none' }

filterFields
[labelKey]
string[]

The fields to filter by.

ignoreFilter
false
boolean

When true, items will not be filtered which is useful for custom filtering.

disabled
boolean
defaultOpen
boolean

The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state.

open
boolean

The controlled open state of the menu. Can be used as v-model:open.

modal
true
boolean

The modality of the dropdown menu.

When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.

searchTerm
''
string
ui
{ content?: SlotClass; input?: SlotClass; empty?: SlotClass; viewport?: SlotClass; arrow?: SlotClass; group?: SlotClass; label?: SlotClass; separator?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; itemTrailingKbds?: SlotClass; itemTrailingKbdsSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemDescription?: SlotClass; itemLabelExternalIcon?: SlotClass; }

Slots

Slot Type
default
{ open: boolean; }
item
{ item: NestedItem<T>; active: boolean; index: number; ui: object; }
item-leading
{ item: NestedItem<T>; active: boolean; index: number; ui: object; }
item-label
{ item: NestedItem<T>; active: boolean; index: number; }
item-description
{ item: NestedItem<T>; active: boolean; index: number; }
item-trailing
{ item: NestedItem<T>; active: boolean; index: number; ui: object; }
empty
{ searchTerm: string; }
content-top
{ sub: boolean; }
content-bottom
{ sub: boolean; }

Emis

Event Type
update:open
[payload: boolean]
update:searchTerm
[value: string]

Thème

app.config.ts
export default defineAppConfig({
  ui: {
    dropdownMenu: {
      slots: {
        content: 'min-w-32 max-h-(--reka-dropdown-menu-content-available-height) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-dropdown-menu-content-transform-origin) flex flex-col',
        input: 'border-b border-default',
        empty: 'text-center text-muted',
        viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
        arrow: 'fill-bg stroke-default',
        group: 'p-1 isolate',
        label: 'w-full flex items-center font-semibold text-highlighted',
        separator: '-mx-1 my-1 h-px bg-border',
        item: 'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75',
        itemLeadingIcon: 'shrink-0',
        itemLeadingAvatar: 'shrink-0',
        itemLeadingAvatarSize: '',
        itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
        itemTrailingIcon: 'shrink-0',
        itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
        itemTrailingKbdsSize: '',
        itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
        itemLabel: 'truncate',
        itemDescription: 'truncate text-muted',
        itemLabelExternalIcon: 'inline-block size-3 align-top text-dimmed'
      },
      variants: {
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        active: {
          true: {
            item: 'text-highlighted before:bg-elevated',
            itemLeadingIcon: 'text-default'
          },
          false: {
            item: [
              'text-default data-highlighted:text-highlighted data-[state=open]:text-highlighted data-highlighted:before:bg-elevated/50 data-[state=open]:before:bg-elevated/50',
              'transition-colors before:transition-colors'
            ],
            itemLeadingIcon: [
              'text-dimmed group-data-highlighted:text-default group-data-[state=open]:text-default',
              'transition-colors'
            ]
          }
        },
        loading: {
          true: {
            itemLeadingIcon: 'animate-spin'
          }
        },
        size: {
          xs: {
            label: 'p-1 text-xs gap-1',
            item: 'p-1 text-xs gap-1',
            empty: 'p-2 text-xs',
            itemLeadingIcon: 'size-4',
            itemLeadingAvatarSize: '3xs',
            itemTrailingIcon: 'size-4',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'sm'
          },
          sm: {
            label: 'p-1.5 text-xs gap-1.5',
            item: 'p-1.5 text-xs gap-1.5',
            empty: 'p-2.5 text-xs',
            itemLeadingIcon: 'size-4',
            itemLeadingAvatarSize: '3xs',
            itemTrailingIcon: 'size-4',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'sm'
          },
          md: {
            label: 'p-1.5 text-sm gap-1.5',
            item: 'p-1.5 text-sm gap-1.5',
            empty: 'p-2.5 text-sm',
            itemLeadingIcon: 'size-5',
            itemLeadingAvatarSize: '2xs',
            itemTrailingIcon: 'size-5',
            itemTrailingKbds: 'gap-0.5',
            itemTrailingKbdsSize: 'md'
          },
          lg: {
            label: 'p-2 text-sm gap-2',
            item: 'p-2 text-sm gap-2',
            empty: 'p-3 text-sm',
            itemLeadingIcon: 'size-5',
            itemLeadingAvatarSize: '2xs',
            itemTrailingIcon: 'size-5',
            itemTrailingKbds: 'gap-1',
            itemTrailingKbdsSize: 'md'
          },
          xl: {
            label: 'p-2 text-base gap-2',
            item: 'p-2 text-base gap-2',
            empty: 'p-3 text-base',
            itemLeadingIcon: 'size-6',
            itemLeadingAvatarSize: 'xs',
            itemTrailingIcon: 'size-6',
            itemTrailingKbds: 'gap-1',
            itemTrailingKbdsSize: 'lg'
          }
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          active: false,
          class: {
            item: 'text-primary data-highlighted:text-primary data-highlighted:before:bg-primary/10 data-[state=open]:before:bg-primary/10',
            itemLeadingIcon: 'text-primary/75 group-data-highlighted:text-primary group-data-[state=open]:text-primary'
          }
        },
        {
          color: 'primary',
          active: true,
          class: {
            item: 'text-primary before:bg-primary/10',
            itemLeadingIcon: 'text-primary'
          }
        }
      ],
      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: {
        dropdownMenu: {
          slots: {
            content: 'min-w-32 max-h-(--reka-dropdown-menu-content-available-height) bg-default shadow-lg rounded-md ring ring-default overflow-hidden data-[state=open]:animate-[scale-in_100ms_var(--ease-out)] data-[state=closed]:animate-[scale-out_100ms_var(--ease-out)] origin-(--reka-dropdown-menu-content-transform-origin) flex flex-col',
            input: 'border-b border-default',
            empty: 'text-center text-muted',
            viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
            arrow: 'fill-bg stroke-default',
            group: 'p-1 isolate',
            label: 'w-full flex items-center font-semibold text-highlighted',
            separator: '-mx-1 my-1 h-px bg-border',
            item: 'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75',
            itemLeadingIcon: 'shrink-0',
            itemLeadingAvatar: 'shrink-0',
            itemLeadingAvatarSize: '',
            itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
            itemTrailingIcon: 'shrink-0',
            itemTrailingKbds: 'hidden lg:inline-flex items-center shrink-0',
            itemTrailingKbdsSize: '',
            itemWrapper: 'flex-1 flex flex-col text-start min-w-0',
            itemLabel: 'truncate',
            itemDescription: 'truncate text-muted',
            itemLabelExternalIcon: 'inline-block size-3 align-top text-dimmed'
          },
          variants: {
            color: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            active: {
              true: {
                item: 'text-highlighted before:bg-elevated',
                itemLeadingIcon: 'text-default'
              },
              false: {
                item: [
                  'text-default data-highlighted:text-highlighted data-[state=open]:text-highlighted data-highlighted:before:bg-elevated/50 data-[state=open]:before:bg-elevated/50',
                  'transition-colors before:transition-colors'
                ],
                itemLeadingIcon: [
                  'text-dimmed group-data-highlighted:text-default group-data-[state=open]:text-default',
                  'transition-colors'
                ]
              }
            },
            loading: {
              true: {
                itemLeadingIcon: 'animate-spin'
              }
            },
            size: {
              xs: {
                label: 'p-1 text-xs gap-1',
                item: 'p-1 text-xs gap-1',
                empty: 'p-2 text-xs',
                itemLeadingIcon: 'size-4',
                itemLeadingAvatarSize: '3xs',
                itemTrailingIcon: 'size-4',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'sm'
              },
              sm: {
                label: 'p-1.5 text-xs gap-1.5',
                item: 'p-1.5 text-xs gap-1.5',
                empty: 'p-2.5 text-xs',
                itemLeadingIcon: 'size-4',
                itemLeadingAvatarSize: '3xs',
                itemTrailingIcon: 'size-4',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'sm'
              },
              md: {
                label: 'p-1.5 text-sm gap-1.5',
                item: 'p-1.5 text-sm gap-1.5',
                empty: 'p-2.5 text-sm',
                itemLeadingIcon: 'size-5',
                itemLeadingAvatarSize: '2xs',
                itemTrailingIcon: 'size-5',
                itemTrailingKbds: 'gap-0.5',
                itemTrailingKbdsSize: 'md'
              },
              lg: {
                label: 'p-2 text-sm gap-2',
                item: 'p-2 text-sm gap-2',
                empty: 'p-3 text-sm',
                itemLeadingIcon: 'size-5',
                itemLeadingAvatarSize: '2xs',
                itemTrailingIcon: 'size-5',
                itemTrailingKbds: 'gap-1',
                itemTrailingKbdsSize: 'md'
              },
              xl: {
                label: 'p-2 text-base gap-2',
                item: 'p-2 text-base gap-2',
                empty: 'p-3 text-base',
                itemLeadingIcon: 'size-6',
                itemLeadingAvatarSize: 'xs',
                itemTrailingIcon: 'size-6',
                itemTrailingKbds: 'gap-1',
                itemTrailingKbdsSize: 'lg'
              }
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              active: false,
              class: {
                item: 'text-primary data-highlighted:text-primary data-highlighted:before:bg-primary/10 data-[state=open]:before:bg-primary/10',
                itemLeadingIcon: 'text-primary/75 group-data-highlighted:text-primary group-data-[state=open]:text-primary'
              }
            },
            {
              color: 'primary',
              active: true,
              class: {
                item: 'text-primary before:bg-primary/10',
                itemLeadingIcon: 'text-primary'
              }
            }
          ],
          defaultVariants: {
            size: 'md'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.

Changelog

No recent changes