2026-02-17 15:03:34 +00:00
|
|
|
<template>
|
|
|
|
|
<Teleport to="body">
|
|
|
|
|
<Transition name="modal">
|
|
|
|
|
<div
|
|
|
|
|
v-if="show"
|
|
|
|
|
class="fixed inset-0 z-[3000] flex items-center justify-center p-4"
|
|
|
|
|
@click="$emit('close')"
|
|
|
|
|
>
|
|
|
|
|
<div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div>
|
|
|
|
|
<div
|
2026-02-17 22:10:38 +00:00
|
|
|
ref="modalRef"
|
2026-02-17 15:03:34 +00:00
|
|
|
@click.stop
|
|
|
|
|
class="glass-card p-6 max-w-lg w-full relative z-10 max-h-[80vh] overflow-y-auto"
|
|
|
|
|
>
|
|
|
|
|
<div class="flex items-start justify-between gap-4 mb-4">
|
|
|
|
|
<h3 class="text-xl font-semibold text-white">{{ title }}</h3>
|
|
|
|
|
<button
|
|
|
|
|
@click="$emit('close')"
|
|
|
|
|
class="p-2 rounded-lg hover:bg-white/10 text-white/70 hover:text-white transition-colors"
|
|
|
|
|
aria-label="Close"
|
|
|
|
|
>
|
|
|
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="text-white/80 prose prose-invert max-w-none">
|
|
|
|
|
<p class="whitespace-pre-wrap">{{ content }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="relatedPath" class="mt-4">
|
|
|
|
|
<router-link
|
|
|
|
|
:to="relatedPath"
|
|
|
|
|
class="inline-flex items-center gap-2 px-4 py-2 glass-button rounded-lg text-sm font-medium"
|
|
|
|
|
@click="$emit('close')"
|
|
|
|
|
>
|
|
|
|
|
Go to related page
|
|
|
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
|
|
|
</svg>
|
|
|
|
|
</router-link>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Transition>
|
|
|
|
|
</Teleport>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-02-17 22:10:38 +00:00
|
|
|
import { ref, computed } from 'vue'
|
|
|
|
|
import { useModalKeyboard } from '@/composables/useModalKeyboard'
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
2026-02-17 15:03:34 +00:00
|
|
|
show: boolean
|
|
|
|
|
title: string
|
|
|
|
|
content: string
|
|
|
|
|
relatedPath?: string
|
|
|
|
|
}>()
|
|
|
|
|
|
2026-02-17 22:10:38 +00:00
|
|
|
const emit = defineEmits<{
|
2026-02-17 15:03:34 +00:00
|
|
|
close: []
|
|
|
|
|
}>()
|
2026-02-17 22:10:38 +00:00
|
|
|
|
|
|
|
|
const modalRef = ref<HTMLElement | null>(null)
|
|
|
|
|
useModalKeyboard(modalRef, computed(() => props.show), () => emit('close'))
|
2026-02-17 15:03:34 +00:00
|
|
|
</script>
|