78 lines
1.6 KiB
Vue
78 lines
1.6 KiB
Vue
|
|
<script setup>
|
||
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||
|
|
|
||
|
|
const threshold = 300
|
||
|
|
const isVisible = ref(false)
|
||
|
|
|
||
|
|
const handleScroll = () => {
|
||
|
|
isVisible.value = window.scrollY > threshold
|
||
|
|
}
|
||
|
|
|
||
|
|
const scrollToTop = () => {
|
||
|
|
window.scrollTo({
|
||
|
|
top: 0,
|
||
|
|
behavior: 'smooth'
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
window.addEventListener('scroll', handleScroll, { passive: true })
|
||
|
|
handleScroll()
|
||
|
|
})
|
||
|
|
|
||
|
|
onBeforeUnmount(() => {
|
||
|
|
window.removeEventListener('scroll', handleScroll)
|
||
|
|
})
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<transition name="fade">
|
||
|
|
<button
|
||
|
|
v-show="isVisible"
|
||
|
|
class="scroll-to-top-button"
|
||
|
|
@click="scrollToTop"
|
||
|
|
aria-label="Прокрутить наверх"
|
||
|
|
>
|
||
|
|
|
||
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||
|
|
<path d="M12 19V5M5 12l7-7 7 7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
|
|
</svg>
|
||
|
|
</button>
|
||
|
|
</transition>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.scroll-to-top-button {
|
||
|
|
position: fixed;
|
||
|
|
bottom: 24px;
|
||
|
|
right: 24px;
|
||
|
|
width: 48px;
|
||
|
|
height: 48px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background-color: var(--primary-color, #18a058);
|
||
|
|
color: white;
|
||
|
|
border: none;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
cursor: pointer;
|
||
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||
|
|
z-index: 1000;
|
||
|
|
transition: transform 0.2s, background-color 0.2s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scroll-to-top-button:hover {
|
||
|
|
background-color: var(--primary-color-hover, #148246);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.fade-enter-active,
|
||
|
|
.fade-leave-active {
|
||
|
|
transition: opacity 0.3s;
|
||
|
|
}
|
||
|
|
.fade-enter-from,
|
||
|
|
.fade-leave-to {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
</style>
|