modal with vimeo player
This commit is contained in:
parent
0511ab89cd
commit
bd6efb24b6
|
|
@ -5,3 +5,15 @@
|
|||
</NuxtLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.page-enter-from,
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
filter: blur(1rem);
|
||||
}
|
||||
</style>
|
||||
3
portfolio-nuxt/components/Modal/Backdrop.vue
Normal file
3
portfolio-nuxt/components/Modal/Backdrop.vue
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<div class="fixed inset-0 bg-black/50 z-5 transition duration-300" />
|
||||
</template>
|
||||
110
portfolio-nuxt/components/Modal/Modal.vue
Normal file
110
portfolio-nuxt/components/Modal/Modal.vue
Normal file
|
|
@ -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>
|
||||
9
portfolio-nuxt/components/Modal/ModalBody.vue
Normal file
9
portfolio-nuxt/components/Modal/ModalBody.vue
Normal file
|
|
@ -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>
|
||||
9
portfolio-nuxt/components/Modal/ModalFooter.vue
Normal file
9
portfolio-nuxt/components/Modal/ModalFooter.vue
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
// import { ref } from 'vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="px-4 py-3">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
34
portfolio-nuxt/components/Modal/ModalHeader.vue
Normal file
34
portfolio-nuxt/components/Modal/ModalHeader.vue
Normal file
|
|
@ -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>
|
||||
|
|
@ -1,18 +1,30 @@
|
|||
<template>
|
||||
<div class="p-1">
|
||||
<div v-show="visible" class="inline-flex bg-black rounded-full text-xs" >
|
||||
<NuxtLink v-if="type === 'document'" class="inline-flex p-1" :to="'/scores/' + work.score" target="_blank">
|
||||
|
||||
<NuxtLink v-if="type === 'document'" class="inline-flex p-1" :to="'/scores/' + work.score">
|
||||
<Icon name="ion:book-outline" color="white" />
|
||||
</NuxtLink>
|
||||
|
||||
<button @click="audioPlayerStore.setSoundCloudTrackID(work.soundcloud_trackid)" v-else-if="type === 'audio'" class="inline-flex p-1">
|
||||
<Icon name="wpf:speaker" color="white" />
|
||||
</button>
|
||||
<button v-else-if="type === 'video'" class="inline-flex p-1">
|
||||
|
||||
<button @click="isOpen = true" v-else-if="type === 'video'" class="inline-flex p-1">
|
||||
<Icon name="fluent:video-48-filled" color="white" />
|
||||
|
||||
<Modal v-model="isOpen">
|
||||
<ModalBody class="aspect-video">
|
||||
<iframe :src="'https://player.vimeo.com/video/' + work.vimeo_trackid" width="100%" height="100%" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
|
||||
</button>
|
||||
|
||||
<button v-else="type === 'image'" class="inline-flex p-1">
|
||||
<Icon name="mdi:camera" color="white" />
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -20,6 +32,8 @@
|
|||
<script setup>
|
||||
import { useAudioPlayerStore } from "@/stores/AudioPlayerStore"
|
||||
const audioPlayerStore = useAudioPlayerStore()
|
||||
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<slot /> <!-- required here only -->
|
||||
<div class="sticky bottom-0 bg-white p-2 flex justify-center">
|
||||
<iframe width="400rem" height="20" scrolling="no" frameborder="no" allow="autoplay"
|
||||
:src="'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + audioPlayerStore.soundcloud_trackid + '&color=%23ff5500&inverse=false&auto_play=true&show_user=true'"></iframe>
|
||||
:src="'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + audioPlayerStore.soundcloud_trackid + '&inverse=false&auto_play=true&show_user=false'"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,8 @@ export default defineNuxtConfig({
|
|||
modules: ['@nuxtjs/tailwindcss', '@nuxt/image', 'nuxt-icon', '@pinia/nuxt'],
|
||||
image: {
|
||||
domains: ['unboundedpress.org']
|
||||
},
|
||||
app: {
|
||||
pageTransition: { name: 'page', mode: 'out-in' }
|
||||
}
|
||||
})
|
||||
|
|
|
|||
17129
portfolio-nuxt/package-lock.json
generated
Normal file
17129
portfolio-nuxt/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -16,6 +16,7 @@
|
|||
"nuxt-icon": "^0.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.7.14",
|
||||
"@pinia/nuxt": "^0.4.11",
|
||||
"pinia": "^2.1.3"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<embed :src="'https://unboundedpress.org/api/scores.files/' + metadata._id.$oid + '/binary'" width="100%" height="900px" />
|
||||
<div class="flex min-h-full items-center justify-center text-center">
|
||||
<embed :src="'https://unboundedpress.org/api/scores.files/' + metadata._id.$oid + '/binary'" class="w-[85%] h-[88vh]" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="bg-gray-100 rounded-lg m-5 grid grid-cols-3 gap-10 bg-white divide-x divide-solid divide-black p-4">
|
||||
<div class="bg-zinc-100 rounded-lg m-5 grid grid-cols-3 gap-10 bg-white divide-x divide-solid divide-black p-4">
|
||||
<div class="px-5">
|
||||
<p class="text-lg">pieces</p>
|
||||
<div class="py-2 ml-3" v-for="item in works">
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
<p class="italic text-sm">{{ work.title }}</p>
|
||||
<div class="grid grid-cols-4">
|
||||
|
||||
<Button :visible="work.score" type="document" :work="work" :link="'/scores/' + work.score"></Button>
|
||||
<Button :visible="work.score" type="document" :work="work"></Button>
|
||||
|
||||
<Button :visible="work.soundcloud_trackid" type="audio" :work="work"></Button>
|
||||
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
<div class="px-5">
|
||||
<p class="text-lg">writings</p>
|
||||
|
||||
<div class="leading-tight py-2 ml-3 text-sm" v-for="item in pubs">
|
||||
{{ item.entryTags.title }}
|
||||
</div>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue