Files
probody/src/components/MyDialog.vue
T
2026-03-28 23:33:20 +03:00

183 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<transition name="modal-fade">
<div class="modal-backdrop" v-if="show" @click.stop="onClose">
<div class="modal" @click.stop>
<header :class="['modal-header', isSuccess ? 'modal-header-success' : 'modal-header-error']">
<slot name="header">
<strong>Заголовок по умолчанию</strong>
</slot>
<button class="modal-btn-close" @click.stop="onClose"
aria-label="Закрыть модальное окно">
×
</button>
</header>
<section class="modal-body">
<slot>Тело по умолчанию</slot>
</section>
<footer :class="['modal-footer', isSuccess ? 'modal-footer-success' : 'modal-footer-error']">
<slot name="footer">
<button @click.stop="onClose">Закрыть</button>
</slot>
</footer>
</div>
</div>
</transition>
</template>
<script setup>
import {defineEmits} from 'vue'
import {useEventListener} from "@vueuse/core";
const emit = defineEmits({
close: null,
'update:show': false,
})
defineProps({
isSuccess: {
type: Boolean,
default: true,
},
show: {
type: Boolean,
default: false
}
})
function onClose() {
emit('update:show')
emit('close')
}
const handleKeydown = (event) => {
if (event.code === "Escape") {
emit('update:show')
}
}
useEventListener("keydown", handleKeydown);
</script>
<style>
:root {
--successColor: #4ee882
}
.modal-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
z-index: 998;
}
.modal {
background: #2f2f2f;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
max-width: 500px;
width: 90%;
border-radius: 5px;
}
.modal-header,
.modal-footer {
padding: 10px;
display: flex;
}
.modal-header {
border-bottom: 1px solid #eeeeee;
justify-content: space-between;
}
.modal-header-success {
color: var(--successColor);
}
.modal-header-error {
color: red;
}
.modal-header button {
color: red;
font-size: 25px;
}
.modal-footer {
justify-content: flex-end;
border-top: 1px solid white;
}
.modal-footer button {
justify-content: flex-end;
border-top: 1px solid white;
padding: 5px;
color: black;
font-size: 15px;
border-radius: 5px;
}
.modal-footer a {
border-radius: 5px;
}
.modal-footer-success button {
background-color: var(--successColor);
border: none;
margin: 3px;
}
.modal-footer-error button {
background: red;
border: none;
}
.modal-body {
position: relative;
padding: 20px 10px;
color: white
}
.modal-btn-close {
border: none;
font-size: 20px;
padding: 0;
cursor: pointer;
font-weight: bold;
color: red;
background: transparent;
}
/* Начало появления: ниже и прозрачный */
.modal-fade-enter-from {
opacity: 0;
}
/* Конец появления: на месте и видим */
.modal-fade-enter-to {
opacity: 1;
}
/* Начало исчезания: на месте и видим */
.modal-fade-leave-from {
opacity: 1;
}
/* Конец исчезания: выше и прозрачный */
.modal-fade-leave-to {
opacity: 0;
}
/* Общие настройки анимации (скорость + плавность) */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: transform 0.5s cubic-bezier(.22, .9, .31, 1), opacity 0.5s ease;
will-change: transform, opacity;
}
</style>