- Page titles in blue primary (#222783) - Double main content margins (px-16 py-24) - Remove blue border above sidebar timer - Remove project color dot, use project color on title text - All delete buttons/icons orange (#E2953C) - Fix collapsed sidebar logo (object-cover object-left) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
2.3 KiB
Vue
90 lines
2.3 KiB
Vue
<template>
|
|
<Teleport to="body">
|
|
<div
|
|
v-if="visible"
|
|
ref="menuEl"
|
|
class="fixed z-50 min-w-36 rounded-md border border-neutral-200 bg-white py-1 shadow-lg"
|
|
:style="{ top: `${y}px`, left: `${x}px` }"
|
|
>
|
|
<button
|
|
v-if="entry"
|
|
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100"
|
|
@click="onCopy"
|
|
>
|
|
<Icon name="mdi:content-copy" size="16" />
|
|
Copier
|
|
</button>
|
|
<button
|
|
v-if="canPaste"
|
|
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100"
|
|
@click="onPaste"
|
|
>
|
|
<Icon name="mdi:content-paste" size="16" />
|
|
Coller
|
|
</button>
|
|
<button
|
|
v-if="entry"
|
|
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-[#E2953C] hover:bg-orange-50"
|
|
@click="onDelete"
|
|
>
|
|
<Icon name="mdi:delete-outline" size="16" />
|
|
Supprimer
|
|
</button>
|
|
</div>
|
|
</Teleport>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { TimeEntry } from '~/services/dto/time-entry'
|
|
|
|
const props = defineProps<{
|
|
visible: boolean
|
|
x: number
|
|
y: number
|
|
entry?: TimeEntry | null
|
|
canPaste: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'close'): void
|
|
(e: 'copy', entry: TimeEntry): void
|
|
(e: 'paste'): void
|
|
(e: 'delete', entry: TimeEntry): void
|
|
}>()
|
|
|
|
const menuEl = ref<HTMLElement | null>(null)
|
|
|
|
function onCopy() {
|
|
if (props.entry) emit('copy', props.entry)
|
|
emit('close')
|
|
}
|
|
|
|
function onPaste() {
|
|
emit('paste')
|
|
emit('close')
|
|
}
|
|
|
|
function onDelete() {
|
|
if (props.entry) emit('delete', props.entry)
|
|
emit('close')
|
|
}
|
|
|
|
function onClickOutside(event: MouseEvent) {
|
|
if (menuEl.value && !menuEl.value.contains(event.target as Node)) {
|
|
emit('close')
|
|
}
|
|
}
|
|
|
|
watch(() => props.visible, (v) => {
|
|
if (v) {
|
|
setTimeout(() => document.addEventListener('click', onClickOutside), 0)
|
|
} else {
|
|
document.removeEventListener('click', onClickOutside)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', onClickOutside)
|
|
})
|
|
</script>
|