Skip to content

Commit

Permalink
modal impl
Browse files Browse the repository at this point in the history
  • Loading branch information
aggre committed Oct 24, 2024
1 parent 817d3d5 commit 4f709aa
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/pages/passport/components/ImageCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ onMounted(async () => {
<img
v-if="image"
:src="image.src"
class="rounded-md w-full max-w-full h-full max-h-full"
class="rounded-md w-full max-w-full h-full object-cover aspect-square max-h-full"
:class="classes"
/>

Expand Down
97 changes: 97 additions & 0 deletions src/pages/passport/components/Modal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script setup lang="ts">
defineProps<{
isVisible: boolean
modalContent: any
handleModalClose: () => void
attrs: { [key: string]: any }
}>()
</script>

<style>
.modal-container {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
}
@media (min-width: 1024px) {
.modal-container {
align-items: center;
}
}
.modal-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.6);
z-index: -1;
}
.modal-content {
display: flex;
flex-direction: column;
padding: 1rem;
background: white;
border-radius: 0.5rem;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
}
@media (min-width: 1024px) {
.modal-content {
}
}
.v-enter-active {
transition: opacity 0.2s ease;
}
.v-leave-active {
transition: opacity 0.2s ease;
}
.v-enter-from {
opacity: 0;
}
.v-leave-to {
opacity: 0;
}
html:has(#modal-container[data-active='true']) {
overflow: hidden;
}
</style>

<template>
<div
id="modal-container"
v-show="isVisible"
class="modal-container z-50"
:data-active="isVisible"
>
<div
class="modal-overlay overflow-y-auto py-6 flex justify-center"
@click="
() => {
handleModalClose()
}
"
>
<Transition>
<component v-show="isVisible" :is="modalContent" v-bind="attrs">
<template #after:description>
<slot name="after:description" />
</template>
</component>
</Transition>
</div>
</div>
</template>
22 changes: 19 additions & 3 deletions src/pages/passport/components/PassportClip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import type { ImageData, PassportClip } from '../types'
const props = defineProps<{
item: PassportClip
truncate?: boolean
classes?: string
}>()
const clubConfig = ref<string>()
Expand Down Expand Up @@ -54,7 +56,11 @@ onMounted(async () => {
<template>
<div
v-if="!!item"
:class="`shadow-md rounded-md p-4 grid gap-4 border border-surface-300 ${item.frameColorHex ? '' : 'bg-surface-200'}`"
class="shadow-md rounded-md h-fit p-4 grid gap-4 border border-surface-300 content-between"
:class="{
'bg-surface-200': !item.frameColorHex,
[props.classes ?? '']: Boolean(props.classes),
}"
:style="{
backgroundColor: item.frameColorHex,
}"
Expand All @@ -63,10 +69,20 @@ onMounted(async () => {
:found="!!item"
:img="item.itemAssetValue"
:type="item.itemAssetType"
:classes="'aspect-square'"
:frame-color-hex="item.frameColorHex"
/>
<p v-html="description"></p>
<article
v-html="description"
:class="{ 'overflow-hidden': props.truncate ?? true }"
></article>
<a v-if="clubName" :href="props.item.clubsUrl">{{ clubName }}</a>
</div>
</template>

<style lang="scss">
article {
&.overflow-hidden p {
@apply truncate;
}
}
</style>
37 changes: 34 additions & 3 deletions src/pages/passport/components/PassportClips.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,55 @@ import { Strings } from '../i18n'
import ImageCard from './ImageCard.vue'
import type { PassportClip } from '../types'
import PassportClipCard from './PassportClip.vue'
import Modal from '@pages/passport/components/Modal.vue'
const props = defineProps<{ clips: PassportClip[] }>()
const i18nBase = i18nFactory(Strings)
let i18n = ref<ReturnType<typeof i18nBase>>(i18nBase(['en']))
const i18n = ref<ReturnType<typeof i18nBase>>(i18nBase(['en']))
const modalVisible = ref(false)
const modalItem = ref<PassportClip>()
const handleOnClick = (item: PassportClip) => {
modalVisible.value = true
modalItem.value = item
}
const modalClose = () => {
modalVisible.value = false
}
onMounted(async () => {
i18n.value = i18nBase(navigator.languages)
})
</script>

<template>
<section class="grid gap-8">
<ul class="grid gap-16 grid-cols-[repeat(auto-fill,minmax(280px,1fr))]">
<ul
class="grid gap-16 grid-cols-[repeat(auto-fill,minmax(280px,1fr))] content-stretch"
>
<li v-if="clips?.length" v-for="clip in clips" class="empty:hidden">
<PassportClipCard :item="clip" />
<PassportClipCard
:item="clip"
:truncate="true"
class="h-full"
@click="
() => {
handleOnClick(clip)
}
"
/>
</li>
</ul>
</section>
<Modal
:is-visible="modalVisible"
:modal-content="PassportClipCard"
:handle-modal-close="modalClose"
:attrs="{
item: modalItem,
truncate: false,
classes: 'max-w-screen-md',
}"
/>
</template>

0 comments on commit 4f709aa

Please sign in to comment.