Newer
Older
gnexus-tasks / frontend / src / components / MdLightbox.vue
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'

// Просмотр картинки на весь экран (лайтбокс): клик по фону, крестик или Esc закрывает.
// Используется для картинок из Markdown-описаний и миниатюр редактора.

defineProps<{
  src: string
  alt?: string
}>()

const emit = defineEmits<{ close: [] }>()

function onKey(e: KeyboardEvent) {
  if (e.key === 'Escape') emit('close')
}

onMounted(() => window.addEventListener('keydown', onKey))
onUnmounted(() => window.removeEventListener('keydown', onKey))
</script>

<template>
  <Teleport to="body">
    <div class="md-lightbox" @click="emit('close')">
      <button class="md-lightbox-close" type="button" aria-label="×" @click="emit('close')">
        <i class="ph ph-x" aria-hidden="true" />
      </button>
      <img :src="src" :alt="alt ?? ''" @click.stop />
    </div>
  </Teleport>
</template>

<style scoped>
.md-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 10, 16, 0.92);
  cursor: zoom-out;
  padding: 2vh 2vw;
}
.md-lightbox img {
  max-width: 96vw;
  max-height: 96vh;
  object-fit: contain;
  cursor: default;
  border: 2px solid var(--border, #2a2e42);
}
.md-lightbox-close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  color: #c0caf5;
  font-size: 28px;
  cursor: pointer;
  padding: 6px;
  line-height: 1;
}
.md-lightbox-close:hover {
  color: #e0af68;
}
</style>