2024-06-04 22:34:51 +02:00

184 lines
3.4 KiB
Vue

<template>
<Teleport to="body">
<div class="modal-container" :style="{ top: y + 'px', left: x + 'px' }" v-if="isModalOpenRef">
<div class="modal-header" @mousedown="startDrag">
<slot name="modal-header" />
<button @click="close"><img src="/assets/icons/close-button-white.svg" /></button>
</div>
<div class="modal-body">
<slot name="modal-body" />
</div>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { defineEmits, onMounted, onUnmounted, ref, watch } from 'vue'
const properties = defineProps({
isModalOpen: {
type: Boolean,
default: false
}
})
watch(
() => properties.isModalOpen,
(value) => {
isModalOpenRef.value = value
}
)
const isModalOpenRef = ref(properties.isModalOpen)
const emit = defineEmits(['modal:close', 'character:create'])
function close() {
emit('modal:close')
}
// make modal draggable
let startX = 0
let startY = 0
let initialX = 0
let initialY = 0
const x = ref(0)
const y = ref(0)
const isDragging = ref(false)
// set modal position center of the screen
onMounted(() => {
x.value = window.innerWidth / 2 - 150
y.value = window.innerHeight / 2 - 100
})
const startDrag = (event: MouseEvent) => {
isDragging.value = true
startX = event.clientX
startY = event.clientY
initialX = x.value
initialY = y.value
event.preventDefault()
}
const drag = (event: MouseEvent) => {
if (!isDragging.value) return
const dx = event.clientX - startX
const dy = event.clientY - startY
x.value = initialX + dx
y.value = initialY + dy
}
const stopDrag = () => {
isDragging.value = false
}
onMounted(() => {
addEventListener('mousemove', drag)
addEventListener('mouseup', stopDrag)
})
onUnmounted(() => {
removeEventListener('mousemove', drag)
removeEventListener('mouseup', stopDrag)
})
</script>
<style lang="scss">
@import '@/assets/scss/main';
.modal-container {
position: fixed;
top: 0;
left: 0;
max-width: 500px;
min-width: 350px;
min-height: 300px;
border-radius: 20px;
background-color: rgba($white, 0.8);
z-index: 999;
.modal-header {
cursor: move;
background-color: rgba($purple, 0.6);
padding: 0 20px;
border-radius: 20px 20px 0 0;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
.modal-title {
margin: 0;
}
button {
width: 40px;
height: 40px;
margin: 0;
padding: 0;
position: relative;
img {
width: 100%;
height: 100%;
}
&:hover::after {
content: '';
position: absolute;
width: 38px;
height: 38px;
left: 1px;
top: 1px;
border-radius: 50%;
background-color: $lilac;
z-index: -1;
}
}
}
.modal-body {
padding: 15px;
.submit {
display: inline-block;
button {
margin-right: 20px;
}
}
button {
padding: 10px 16px;
min-width: 100px;
border-radius: 5px;
}
p {
color: $black;
}
.modal-form {
display: inline;
.form-fields {
display: flex;
flex-direction: column;
margin-bottom: 20px;
label {
margin-bottom: 10px;
color: $black;
}
input {
max-width: 250px;
border: 1px solid $purple;
border-radius: 5px;
background-color: rgba($white, 0.5);
padding: 10px;
}
}
}
}
}
</style>