Files
hossein-por-shop/frontend/components/global/Modal.vue
T
2025-02-08 23:47:43 +03:30

95 lines
3.1 KiB
Vue

<script setup lang="ts">
// types
type Props = {
modelValue: boolean;
icon?: string;
title: string;
iconSize?: string;
};
type Emits = {
"update:modelValue": [value: boolean];
close: [value: null];
};
// props
const props = defineProps<Props>();
const { modelValue } = toRefs(props);
// emit
const emit = defineEmits<Emits>();
// computed
const isShow = computed({
get: () => modelValue.value ?? false,
set: (value) => {
emit("update:modelValue", value);
emit("close", null);
},
});
</script>
<template>
<DialogRoot v-model:open="isShow">
<DialogTrigger>
<slot name="trigger" />
</DialogTrigger>
<DialogPortal>
<DialogOverlay
class="bg-black/50 backdrop-blur-sm data-[state=open]:animate-overlay-show fixed inset-0 z-999"
/>
<div
class="fixed inset-0 w-full h-svh z-9999 flex-center"
v-if="isShow"
>
<div
class="overflow-y-auto max-h-svh absolute left-[50%] py-10 w-fit max-w-[50rem] translate-x-[-50%]"
>
<DialogContent
class="data-[state=open]:animate-content-show text-black font-iran-yekan-x focus:outline-none z-[100]"
>
<div
class="rounded-3xl bg-white shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px]"
>
<div
class="w-full flex items-center px-6 justify-between py-[1.5rem] border-b border-slate-200"
>
<DialogClose
class="inline-flex size-8 items-center justify-center transition-all rounded-full bg-gray-50 border border-slate-200 hover:border-black focus:outline-none"
aria-label="Close"
>
<Icon
name="bi:x-lg"
class="**:fill-black"
/>
</DialogClose>
<DialogTitle
class="typo-sub-h-xl font-semibold flex items-center gap-3"
>
{{ title }}
<Icon
v-if="!!icon"
:name="icon"
:size="iconSize"
/>
</DialogTitle>
</div>
<div class="w-full px-6">
<slot name="content" />
</div>
</div>
</DialogContent>
</div>
</div>
</DialogPortal>
</DialogRoot>
</template>
<style scoped></style>