Contexte Menu
Utilisation
Utilisez tout ce que vous voulez dans l'emplacement par défaut du menu contextuel, et cliquez avec le bouton droit dessus pour afficher le menu.
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[][]>([
[
{
label: 'Appearance',
children: [
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
]
}
],
[
{
label: 'Show Sidebar',
kbds: ['meta', 's']
},
{
label: 'Show Toolbar',
kbds: ['shift', 'meta', 'd']
},
{
label: 'Collapse Pinned Tabs',
disabled: true
}
],
[
{
label: 'Refresh the Page'
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
},
{
type: 'separator'
},
{
label: 'Developer',
children: [
[
{
label: 'View Source',
kbds: ['meta', 'shift', 'u']
},
{
label: 'Developer Tools',
kbds: ['option', 'meta', 'i']
},
{
label: 'Inspect Elements',
kbds: ['option', 'meta', 'c']
}
],
[
{
label: 'JavaScript Console',
kbds: ['option', 'meta', 'j']
}
]
]
}
]
])
</script>
<template>
<UContextMenu :items="items">
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[][]>([
[
{
label: 'Appearance',
children: [
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
]
}
],
[
{
label: 'Show Sidebar',
kbds: ['meta', 's']
},
{
label: 'Show Toolbar',
kbds: ['shift', 'meta', 'd']
},
{
label: 'Collapse Pinned Tabs',
disabled: true
}
],
[
{
label: 'Refresh the Page'
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
},
{
type: 'separator'
},
{
label: 'Developer',
children: [
[
{
label: 'View Source',
kbds: ['meta', 'shift', 'u']
},
{
label: 'Developer Tools',
kbds: ['option', 'meta', 'i']
},
{
label: 'Inspect Elements',
kbds: ['option', 'meta', 'c']
}
],
[
{
label: 'JavaScript Console',
kbds: ['option', 'meta', 'j']
}
]
]
}
]
])
</script>
<template>
<UContextMenu :items="items">
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template>Éléments
Utilisez le prop items comme un tableau d'objets avec les propriétés suivantes:
- x
label?: stringxx{lang="ts-type"} - x
icon?: stringx{lang="ts-type"} - x
avatar?: AvatarPropsx{lang="ts-type"} - xx
kbds?: string[] | KbdProps[]xx{lang="ts-type"} Xph079xxxtype?: "link" | "label" | "separator" | "checkbox"x{lang="ts-type"}x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - x
disabled?: booleanx{lang="ts-type"} - xx
slot?: stringx{lang="ts-type"}x - x
onSelect?: (e: Event) => voidXph113xxxonUpdateChecked?: (checked: boolean) => voidx{lang="ts-type"}x children?: ContextMenuItem[] | ContextMenuItem[][]- x
class?: anyx{lang="ts-type"} - x
ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: 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 { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[][]>([
[
{
label: 'Appearance',
children: [
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
]
}
],
[
{
label: 'Show Sidebar',
kbds: ['meta', 's']
},
{
label: 'Show Toolbar',
kbds: ['shift', 'meta', 'd']
},
{
label: 'Collapse Pinned Tabs',
disabled: true
}
],
[
{
label: 'Refresh the Page'
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
},
{
type: 'separator'
},
{
label: 'Developer',
children: [
[
{
label: 'View Source',
kbds: ['meta', 'shift', 'u']
},
{
label: 'Developer Tools',
kbds: ['option', 'meta', 'i']
},
{
label: 'Inspect Elements',
kbds: ['option', 'meta', 'c']
}
],
[
{
label: 'JavaScript Console',
kbds: ['option', 'meta', 'j']
}
]
]
}
]
])
</script>
<template>
<UContextMenu
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[][]>([
[
{
label: 'Appearance',
children: [
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
]
}
],
[
{
label: 'Show Sidebar',
kbds: ['meta', 's']
},
{
label: 'Show Toolbar',
kbds: ['shift', 'meta', 'd']
},
{
label: 'Collapse Pinned Tabs',
disabled: true
}
],
[
{
label: 'Refresh the Page'
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
},
{
type: 'separator'
},
{
label: 'Developer',
children: [
[
{
label: 'View Source',
kbds: ['meta', 'shift', 'u']
},
{
label: 'Developer Tools',
kbds: ['option', 'meta', 'i']
},
{
label: 'Inspect Elements',
kbds: ['option', 'meta', 'c']
}
],
[
{
label: 'JavaScript Console',
kbds: ['option', 'meta', 'j']
}
]
]
}
]
])
</script>
<template>
<UContextMenu
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template>items pour créer des groupes d'éléments séparés.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.Size
Utilisez la prop size pour modifier la taille du menu contextuel.
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
size="xl"
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
size="xl"
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template>Modale
Utilisez la prop modal pour contrôler si le ContextMenu bloque l'interaction avec le contenu extérieur.
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
:modal="false"
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
:modal="false"
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template>Désactivé
Utilisez la prop disabled pour désactiver le Menu contextuel.
<script setup lang="ts">
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
disabled
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const items = ref<ContextMenuItem[]>([
{
label: 'System',
icon: 'i-lucide-monitor'
},
{
label: 'Light',
icon: 'i-lucide-sun'
},
{
label: 'Dark',
icon: 'i-lucide-moon'
}
])
</script>
<template>
<UContextMenu
disabled
:items="items"
:ui="{
content: 'w-48'
}"
>
<div
class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72"
>
Right click here
</div>
</UContextMenu>
</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 { ContextMenuItem } from '@nuxt/ui'
const showSidebar = ref(true)
const showToolbar = ref(false)
const items = computed<ContextMenuItem[]>(() => [{
label: 'View',
type: 'label' as const
}, {
type: 'separator' as const
}, {
label: 'Show Sidebar',
type: 'checkbox' as const,
checked: showSidebar.value,
onUpdateChecked(checked: boolean) {
showSidebar.value = checked
},
onSelect(e: Event) {
e.preventDefault()
}
}, {
label: 'Show Toolbar',
type: 'checkbox' as const,
checked: showToolbar.value,
onUpdateChecked(checked: boolean) {
showToolbar.value = checked
}
}, {
label: 'Collapse Pinned Tabs',
type: 'checkbox' as const,
disabled: true
}])
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const showSidebar = ref(true)
const showToolbar = ref(false)
const items = computed<ContextMenuItem[]>(() => [{
label: 'View',
type: 'label' as const
}, {
type: 'separator' as const
}, {
label: 'Show Sidebar',
type: 'checkbox' as const,
checked: showSidebar.value,
onUpdateChecked(checked: boolean) {
showSidebar.value = checked
},
onSelect(e: Event) {
e.preventDefault()
}
}, {
label: 'Show Toolbar',
type: 'checkbox' as const,
checked: showToolbar.value,
onUpdateChecked(checked: boolean) {
showToolbar.value = checked
}
}, {
label: 'Collapse Pinned Tabs',
type: 'checkbox' as const,
disabled: true
}])
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>
</template>
checked, il est recommandé d'envelopper votre baie 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 { ContextMenuItem } from '@nuxt/ui'
const items: ContextMenuItem[][] = [
[
{
label: 'View',
icon: 'i-lucide-eye'
},
{
label: 'Copy',
icon: 'i-lucide-copy'
},
{
label: 'Edit',
icon: 'i-lucide-pencil'
}
],
[
{
label: 'Delete',
color: 'error' as const,
icon: 'i-lucide-trash'
}
]
]
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>
</template>
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
#{{ 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 { ContextMenuItem } from '@nuxt/ui'
const loading = ref(true)
const items = [
{
label: 'Refresh the Page',
slot: 'refresh' as const
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
}
] satisfies ContextMenuItem[]
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
<template #refresh-label>
{{ loading ? 'Refreshing...' : 'Refresh the Page' }}
</template>
<template #refresh-trailing>
<UIcon v-if="loading" name="i-lucide-loader-circle" class="shrink-0 size-5 text-primary animate-spin" />
</template>
</UContextMenu>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ContextMenuItem } from '@nuxt/ui'
const loading = ref(true)
const items = [
{
label: 'Refresh the Page',
slot: 'refresh' as const
},
{
label: 'Clear Cookies and Refresh'
},
{
label: 'Clear Cache and Refresh'
}
] satisfies ContextMenuItem[]
</script>
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
<template #refresh-label>
{{ loading ? 'Refreshing...' : 'Refresh the Page' }}
</template>
<template #refresh-trailing>
<UIcon v-if="loading" name="i-lucide-loader-circle" class="shrink-0 size-5 text-primary animate-spin" />
</template>
</UContextMenu>
</template>
#item, #item-leading, #item-label et #item-trailing pour personnaliser tous les éléments.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 les raccourcis et renvoie un objet compatible avec defineShortcuts.
<script setup lang="ts">
const items = [
[{
label: 'Show Sidebar',
kbds: ['meta', 'S'],
onSelect() {
console.log('Show Sidebar clicked')
}
}, {
label: 'Show Toolbar',
kbds: ['shift', 'meta', 'D'],
onSelect() {
console.log('Show Toolbar clicked')
}
}, {
label: 'Collapse Pinned Tabs',
disabled: true
}], [{
label: 'Refresh the Page'
}, {
label: 'Clear Cookies and Refresh'
}, {
label: 'Clear Cache and Refresh'
}, {
type: 'separator' as const
}, {
label: 'Developer',
children: [[{
label: 'View Source',
kbds: ['option', 'meta', 'U'],
onSelect() {
console.log('View Source clicked')
}
}, {
label: 'Developer Tools',
kbds: ['option', 'meta', 'I'],
onSelect() {
console.log('Developer Tools clicked')
}
}], [{
label: 'Inspect Elements',
kbds: ['option', 'meta', 'C'],
onSelect() {
console.log('Inspect Elements clicked')
}
}], [{
label: 'JavaScript Console',
kbds: ['option', 'meta', 'J'],
onSelect() {
console.log('JavaScript Console clicked')
}
}]]
}]
]
defineShortcuts(extractShortcuts(items))
</script>
select de l'élément correspondant.API
Props équipements
| Prop | Default | Type |
|---|---|---|
size | 'md' | "sm" | "md" | "xs" | "lg" | "xl" |
items | T | |
checkedIcon | appConfig.ui.icons.check | anyThe icon displayed when an item is checked. |
loadingIcon | appConfig.ui.icons.loading | anyThe icon displayed when an item is loading. |
externalIcon | true | anyThe icon displayed when the item is an external link.
Set to |
content | ContextMenuContentProps & Partial<EmitsToProps<MenuContentEmits>>The content of the menu. | |
portal | true | string | false | true | HTMLElementRender 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. |
disabled | boolean | |
modal | true | boolean The modality of the dropdown menu. When set to |
pressOpenDelay | 700 | numberThe duration from when the trigger is pressed until the menu opens. |
ui | { content?: SlotClass; viewport?: 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 | {} |
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; } |
content-top | { sub: boolean; } |
content-bottom | { sub: boolean; } |
Emis
| Event | Type |
|---|---|
update:open | [payload: boolean] |
Thème
export default defineAppConfig({
ui: {
contextMenu: {
slots: {
content: 'min-w-32 max-h-(--reka-context-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-context-menu-content-transform-origin) flex flex-col',
viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
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',
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',
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',
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',
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',
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'
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
contextMenu: {
slots: {
content: 'min-w-32 max-h-(--reka-context-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-context-menu-content-transform-origin) flex flex-col',
viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1',
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',
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',
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',
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',
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',
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'
}
}
}
})
]
})