Files
crm/apps/web/src/components/ui/UiModal.vue
T

126 lines
2.3 KiB
Vue

<script setup lang="ts">
import { onUnmounted, watch } from 'vue';
import UiIcon from '@/components/UiIcon.vue';
const props = defineProps<{
open: boolean;
title: string;
}>();
const emit = defineEmits<{
close: [];
}>();
watch(
() => props.open,
(open) => {
document.body.style.overflow = open ? 'hidden' : '';
},
);
onUnmounted(() => {
document.body.style.overflow = '';
});
function onBackdrop(event: MouseEvent) {
if (event.target === event.currentTarget) emit('close');
}
</script>
<template>
<Teleport to="body">
<div v-if="open" class="backdrop" @click="onBackdrop">
<section
class="dialog"
role="dialog"
aria-modal="true"
:aria-label="title"
@click.stop
>
<header class="head">
<h2>{{ title }}</h2>
<button type="button" class="close" aria-label="بستن" @click="emit('close')">
<UiIcon name="x" :size="18" />
</button>
</header>
<div class="body">
<slot />
</div>
<footer v-if="$slots.footer" class="foot">
<slot name="footer" />
</footer>
</section>
</div>
</Teleport>
</template>
<style scoped>
.backdrop {
position: fixed;
inset: 0;
z-index: 80;
display: grid;
place-items: center;
padding: 1.25rem;
background: rgba(15, 23, 42, 0.35);
}
.dialog {
width: min(880px, 100%);
max-height: min(88vh, 880px);
display: flex;
flex-direction: column;
background: #fff;
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: 0 18px 48px rgba(15, 23, 42, 0.16);
overflow: hidden;
}
.head,
.body,
.foot {
padding: var(--pad-modal);
}
.head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding-bottom: 0;
}
.head h2 {
margin: 0;
font-size: 1.05rem;
font-weight: 800;
}
.close {
width: var(--control-h);
height: var(--control-h);
border: 1px solid var(--line);
border-radius: var(--radius);
background: #fff;
color: var(--muted);
display: grid;
place-items: center;
cursor: pointer;
}
.body {
overflow: auto;
min-height: 0;
padding-top: 1rem;
}
.foot {
display: flex;
justify-content: flex-start;
gap: 0.5rem;
padding-top: 0;
border-top: 1px solid #f1f5f9;
}
</style>