108 lines
3.4 KiB
Vue
108 lines
3.4 KiB
Vue
<script setup lang="ts">
|
|
// types
|
|
|
|
type Props = {
|
|
modelValue: boolean;
|
|
icon?: string;
|
|
title: string;
|
|
iconSize?: string;
|
|
contectClass?: 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 = ref(modelValue.value);
|
|
|
|
watch(
|
|
() => isShow.value,
|
|
(nv) => {
|
|
if (!nv) {
|
|
emit("update:modelValue", false);
|
|
emit("close", null);
|
|
}
|
|
}
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<DialogRoot
|
|
v-model:open="isShow"
|
|
@update:open="
|
|
(state) => {
|
|
!state ? (isShow = false) : null;
|
|
}
|
|
"
|
|
>
|
|
<DialogTrigger :class="!$slots['trigger'] ? 'hidden' : ''">
|
|
<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="contectClass"
|
|
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-2xl 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>
|