modal with vimeo player
parent
0511ab89cd
commit
bd6efb24b6
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fixed inset-0 bg-black/50 z-5 transition duration-300" />
|
||||||
|
</template>
|
@ -0,0 +1,110 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogPanel,
|
||||||
|
TransitionChild,
|
||||||
|
TransitionRoot,
|
||||||
|
} from '@headlessui/vue'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
modelValue?: boolean
|
||||||
|
persistent?: boolean
|
||||||
|
fullscreen?: boolean
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
modelValue: false,
|
||||||
|
persistent: false,
|
||||||
|
fullscreen: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: boolean): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { modelValue } = toRefs(props)
|
||||||
|
|
||||||
|
const isOpen = ref(modelValue.value)
|
||||||
|
|
||||||
|
watch(modelValue, (value) => {
|
||||||
|
isOpen.value = value
|
||||||
|
})
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
isOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function openModal() {
|
||||||
|
isOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function onModalClose() {
|
||||||
|
if (!props.persistent)
|
||||||
|
closeModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(isOpen, (value) => {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
isOpen,
|
||||||
|
open: openModal,
|
||||||
|
close: closeModal,
|
||||||
|
}
|
||||||
|
|
||||||
|
provide('modal', api)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ClientOnly>
|
||||||
|
<slot name="activator" :open="openModal" :on="{ click: openModal }" />
|
||||||
|
|
||||||
|
<TransitionRoot appear :show="isOpen" as="template">
|
||||||
|
<Dialog as="div" class="relative z-10" @close="onModalClose">
|
||||||
|
<TransitionChild
|
||||||
|
as="template"
|
||||||
|
enter="duration-300 ease-out"
|
||||||
|
enter-from="opacity-0"
|
||||||
|
enter-to="opacity-100"
|
||||||
|
leave="duration-200 ease-in"
|
||||||
|
leave-from="opacity-100"
|
||||||
|
leave-to="opacity-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 bg-black bg-opacity-25" />
|
||||||
|
</TransitionChild>
|
||||||
|
|
||||||
|
<div class="fixed inset-0 overflow-y-auto">
|
||||||
|
<div
|
||||||
|
class="flex min-h-full items-center justify-center text-center"
|
||||||
|
:class="{
|
||||||
|
'p-4': !fullscreen,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<TransitionChild
|
||||||
|
as="template"
|
||||||
|
enter="duration-300 ease-out"
|
||||||
|
enter-from="opacity-0 scale-95"
|
||||||
|
enter-to="opacity-100 scale-100"
|
||||||
|
leave="duration-200 ease-in"
|
||||||
|
leave-from="opacity-100 scale-100"
|
||||||
|
leave-to="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<DialogPanel
|
||||||
|
class="w-full transform overflow-hidden bg-white text-left align-middle shadow-xl transition-all"
|
||||||
|
:class="{
|
||||||
|
'h-screen': fullscreen,
|
||||||
|
'max-w-[85%] rounded-lg': !fullscreen,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</DialogPanel>
|
||||||
|
</TransitionChild>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</TransitionRoot>
|
||||||
|
</ClientOnly>
|
||||||
|
</template>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DialogDescription } from '@headlessui/vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogDescription class="px-4 py-3 text-sm text-gray-800">
|
||||||
|
<slot />
|
||||||
|
</DialogDescription>
|
||||||
|
</template>
|
@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// import { ref } from 'vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="px-4 py-3">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -0,0 +1,34 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DialogTitle } from '@headlessui/vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
dismissable?: boolean
|
||||||
|
titleClass?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<Props>()
|
||||||
|
|
||||||
|
const api = inject('modal')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogTitle
|
||||||
|
as="div"
|
||||||
|
class="flex gap-2 justify-between items-center px-4 pt-3"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="text-lg font-medium leading-6 text-gray-900"
|
||||||
|
:class="titleClass"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</h3>
|
||||||
|
<slot v-if="dismissable" name="dismissable">
|
||||||
|
<button
|
||||||
|
class="text-2xl text-gray-500 appearance-none px-2 -mr-2"
|
||||||
|
@click="api.close"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</slot>
|
||||||
|
</DialogTitle>
|
||||||
|
</template>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue