Make sticky card functional
This commit is contained in:
@@ -1,10 +1,27 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
// import
|
// import
|
||||||
|
|
||||||
import useGetProduct from "~/composables/api/product/useGetProduct";
|
import useGetProduct from "~/composables/api/product/useGetProduct";
|
||||||
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
|
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
showChatButton: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// props
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
// emits
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:showChatButton"]);
|
||||||
|
|
||||||
|
// provide / inject
|
||||||
|
|
||||||
|
const { selectedVariant } = inject("productVariant") as ProductVariantProvideType;
|
||||||
|
|
||||||
// state
|
// state
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -12,12 +29,32 @@ const id = route.params.id as string | undefined;
|
|||||||
|
|
||||||
const { data: product } = useGetProduct(id);
|
const { data: product } = useGetProduct(id);
|
||||||
|
|
||||||
const { selectedVariant } = inject("productVariant") as ProductVariantProvideType;
|
const videoSectionEl = useTemplateRef<HTMLDivElement>("videoSectionEl");
|
||||||
|
|
||||||
|
const { bottom: videoSectionBottomBounding, height: videoSectionHeightBounding } = useElementBounding(videoSectionEl);
|
||||||
|
const isVideoSectionVisible = useElementVisibility(videoSectionEl, {
|
||||||
|
rootMargin: "0px 0px -20% 0px",
|
||||||
|
});
|
||||||
|
|
||||||
|
// computed
|
||||||
|
|
||||||
|
const isVideoSectionHittingBottom = computed(() => {
|
||||||
|
return videoSectionBottomBounding.value < videoSectionHeightBounding.value - 100;
|
||||||
|
});
|
||||||
|
|
||||||
|
// watch
|
||||||
|
|
||||||
|
watch([isVideoSectionVisible, isVideoSectionHittingBottom], ([isVideoSectionVisible, isVideoSectionHittingBottom]) => {
|
||||||
|
emit("update:showChatButton", !(isVideoSectionVisible && !isVideoSectionHittingBottom));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section v-if="selectedVariant?.video" class="h-[110svh] w-full relative bg-black mt-[5rem]">
|
<section
|
||||||
|
v-if="selectedVariant?.video"
|
||||||
|
ref="videoSectionEl"
|
||||||
|
class="h-[110svh] w-full relative bg-black mt-[5rem]"
|
||||||
|
>
|
||||||
<video
|
<video
|
||||||
:src="selectedVariant.video"
|
:src="selectedVariant.video"
|
||||||
class="object-cover absolute size-full"
|
class="object-cover absolute size-full"
|
||||||
@@ -28,14 +65,22 @@ const { selectedVariant } = inject("productVariant") as ProductVariantProvideTyp
|
|||||||
loop
|
loop
|
||||||
/>
|
/>
|
||||||
<div class="size-full absolute inset-0 bg-black/20" />
|
<div class="size-full absolute inset-0 bg-black/20" />
|
||||||
<div class="absolute max-sm:flex items-center justify-center max-sm:px-5 sm:right-10 bottom-10 w-full">
|
<Transition
|
||||||
<StickyCard
|
name="fade"
|
||||||
:color="selectedVariant.color!"
|
:duration="150"
|
||||||
:price="selectedVariant.price"
|
>
|
||||||
:picture="selectedVariant.images[0].image"
|
<div
|
||||||
:title="product!.name"
|
v-if="isVideoSectionVisible && !isVideoSectionHittingBottom"
|
||||||
class="max-sm:!w-full"
|
class="fixed max-sm:flex max-sm:w-full items-center justify-center max-sm:px-5 sm:right-10 bottom-10 h-fit w-fit"
|
||||||
/>
|
>
|
||||||
</div>
|
<StickyCard
|
||||||
|
:color="selectedVariant.color!"
|
||||||
|
:price="selectedVariant.price"
|
||||||
|
:picture="selectedVariant.images[0].image"
|
||||||
|
:title="product!.name"
|
||||||
|
class="max-sm:!w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user