feat. ScrollTop 버튼 추가
This commit is contained in:
69
layers/components/atoms/Button/ScrollTop.vue
Normal file
69
layers/components/atoms/Button/ScrollTop.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
parentRef: HTMLElement | null
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { y: windowY } = useWindowScroll({ behavior: 'smooth' })
|
||||
const { height: viewportH } = useWindowSize()
|
||||
|
||||
const parentEl = toRef(props, 'parentRef')
|
||||
const { bottom: parentBottom } = useElementBounding(parentEl)
|
||||
|
||||
const showBtn = computed(() => windowY.value > 0)
|
||||
|
||||
const offsetY = 12
|
||||
|
||||
const pinToParent = computed(() => {
|
||||
if (!parentBottom.value) return false
|
||||
return parentBottom.value <= viewportH.value - offsetY
|
||||
})
|
||||
|
||||
const positionClasses = computed(() =>
|
||||
pinToParent.value
|
||||
? 'absolute bottom-[12px] right-[12px] md:bottom-[40px] md:right-[40px]'
|
||||
: 'fixed bottom-[12px] right-[12px] md:bottom-[40px] md:right-[40px]'
|
||||
)
|
||||
|
||||
const handleScrollToTop = () => {
|
||||
windowY.value = 0
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="fade">
|
||||
<button
|
||||
v-if="showBtn"
|
||||
:class="['btn-top', positionClasses]"
|
||||
@click="handleScrollToTop"
|
||||
>
|
||||
<AtomsIconsTopLine class="icon-top" />
|
||||
<span class="sr-only">top</span>
|
||||
</button>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.btn-top {
|
||||
@apply rounded-full flex items-center justify-center bg-black/20 z-[100]
|
||||
w-[40px] h-[40px] md:w-[48px] md:h-[48px]
|
||||
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.06)] before:rounded-full before:transition-all before:duration-300 before:ease-in-out
|
||||
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-full after:opacity-0 after:transition-all after:duration-300 after:ease-in-out;
|
||||
}
|
||||
.btn-top:hover {
|
||||
@apply after:opacity-10;
|
||||
}
|
||||
.btn-top:hover .icon-top {
|
||||
@apply opacity-100;
|
||||
}
|
||||
.icon-top {
|
||||
@apply opacity-50 transition-opacity duration-300 ease-in-out;
|
||||
}
|
||||
|
||||
[data-theme='light'] {
|
||||
.btn-top {
|
||||
@apply bg-white/10;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user