-
Notifications
You must be signed in to change notification settings - Fork 731
/
CommonActionMenu.vue
104 lines (90 loc) · 3.04 KB
/
CommonActionMenu.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
<script setup lang="ts">
import { computed, ref, toRefs } from 'vue'
import getUuid from '#shared/utils/getUuid.ts'
import type { ObjectLike } from '#shared/types/utils.ts'
import CommonPopover from '#desktop/components/CommonPopover/CommonPopover.vue'
import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
import CommonPopoverMenu from '#desktop/components/CommonPopover/CommonPopoverMenu.vue'
import { usePopover } from '#desktop/components/CommonPopover/usePopover.ts'
import type { ButtonSize } from '#desktop/components/CommonButton/types.ts'
import type {
MenuItem,
Orientation,
Placement,
} from '#desktop/components/CommonPopover/types.ts'
import { usePopoverMenu } from '#desktop/components/CommonPopover/usePopoverMenu.ts'
interface Props {
actions: MenuItem[]
entity?: ObjectLike
buttonSize?: ButtonSize
placement?: Placement
orientation?: Orientation
noSingleActionMode?: boolean
}
const props = withDefaults(defineProps<Props>(), {
buttonSize: 'medium',
placement: 'end',
orientation: 'autoVertical',
})
const popoverMenu = ref<InstanceType<typeof CommonPopoverMenu>>()
const { popover, isOpen: popoverIsOpen, popoverTarget, toggle } = usePopover()
const { actions, entity } = toRefs(props)
const { filteredMenuItems, singleMenuItemPresent, singleMenuItem } =
usePopoverMenu(actions, entity, { provides: true })
const entityId = computed(() => props.entity?.id || getUuid())
const menuId = computed(() => `popover-${entityId.value}`)
const singleActionMode = computed(() => {
if (props.noSingleActionMode) return false
return singleMenuItemPresent.value
})
const buttonVariantClass = computed(() => {
if (singleMenuItem.value?.variant === 'secondary') return 'text-blue-800'
if (singleMenuItem.value?.variant === 'danger') return 'text-red-500'
return 'text-stone-200 dark:text-neutral-500'
})
</script>
<template>
<div
v-if="filteredMenuItems && filteredMenuItems.length > 0"
class="inline-block"
>
<CommonButton
v-if="singleActionMode"
:class="buttonVariantClass"
:size="buttonSize"
:aria-label="$t(singleMenuItem?.label)"
:icon="singleMenuItem?.icon"
@click="singleMenuItem?.onClick?.(entity as ObjectLike)"
/>
<CommonButton
v-else
:id="entity?.id || entityId"
ref="popoverTarget"
:aria-label="$t('Action menu button')"
aria-haspopup="true"
:aria-controls="menuId"
class="text-stone-200 dark:text-neutral-500"
:class="{
'outline outline-1 outline-offset-1 outline-blue-800': popoverIsOpen,
}"
:size="buttonSize"
icon="three-dots-vertical"
@click="toggle"
/>
<CommonPopover
v-if="!singleActionMode"
:id="menuId"
ref="popover"
:placement="placement"
:orientation="orientation"
:owner="popoverTarget"
>
<CommonPopoverMenu
ref="popoverMenu"
:entity="entity"
:popover="popover"
/>
</CommonPopover>
</div>
</template>