Files
speckle-server/packages/frontend-2/components/layout/Dialog.vue
T
Kristaps Fabians Geikins b02a07e2b6 feat: Frontend 2.0 MVP
2023-05-08 10:47:01 +03:00

115 lines
3.0 KiB
Vue

<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" class="relative z-40" @close="open = false">
<TransitionChild
as="template"
enter="ease-out duration-300"
enter-from="opacity-0"
enter-to="opacity-100"
leave="ease-in duration-200"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div
class="fixed inset-0 bg-neutral-100/70 dark:bg-neutral-900/70 transition-opacity"
/>
</TransitionChild>
<div class="fixed inset-0 z-10 overflow-y-auto">
<div class="flex min-h-full justify-center p-4 text-center items-center sm:p-0">
<TransitionChild
as="template"
enter="ease-out duration-300"
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enter-to="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
@after-leave="$emit('fully-closed')"
>
<DialogPanel
:class="[
'transform rounded-lg bg-foundation text-left shadow-xl transition-all',
widthClasses
]"
>
<div class="relative">
<slot>Put your content here!</slot>
<button
v-if="!hideCloser"
class="absolute top-0 right-0 text-foreground"
@click="open = false"
>
<XMarkIcon class="h-6 w-6" />
</button>
</div>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup lang="ts">
import { Dialog, DialogPanel, TransitionChild, TransitionRoot } from '@headlessui/vue'
import { XMarkIcon } from '@heroicons/vue/24/outline'
type MaxWidthValue = 'sm' | 'md' | 'lg' | 'xl'
const emit = defineEmits<{
(e: 'update:open', v: boolean): void
(e: 'fully-closed'): void
}>()
const props = defineProps<{
open: boolean
maxWidth?: MaxWidthValue
hideCloser?: boolean
}>()
const open = computed({
get: () => props.open,
set: (newVal) => emit('update:open', newVal)
})
const maxWidthWeight = computed(() => {
switch (props.maxWidth) {
case 'sm':
return 0
case 'md':
return 1
case 'lg':
return 2
case 'xl':
return 3
default:
return 10000
}
})
const widthClasses = computed(() => {
const classParts: string[] = [
'px-4 pt-4 pb-4 w-full',
'sm:my-8 sm:w-full sm:max-w-xl sm:p-6'
]
if (maxWidthWeight.value >= 1) {
classParts.push('md:max-w-2xl')
}
if (maxWidthWeight.value >= 2) {
classParts.push('lg:max-w-4xl')
}
if (maxWidthWeight.value >= 3) {
classParts.push('xl:max-w-6xl')
}
if (maxWidthWeight.value >= 4) {
classParts.push('2xl:max-w-7xl')
}
return classParts.join(' ')
})
</script>