nuxt-arch
Version:
Arch is a Nuxt 3 template for creating your personal website less than a minute.
116 lines (105 loc) • 2.67 kB
text/typescript
import { defineComponent, h, onBeforeUnmount, ref } from 'vue'
import { useNuxtApp } from '#app'
export default defineComponent({
name: 'NuxtScrollIndicator',
props: {
height: {
type: Number,
default: 3,
},
color: {
type: String,
default: 'linear-gradient(to right, #00dc82 0%,#34cdfe 50%,#0047e1 100%)',
required: false,
},
background: {
type: String,
default: 'transparent',
},
shadow: {
type: String,
default: 'none',
},
borderRadius: {
type: Number,
default: 0,
},
elementId: {
type: String,
required: false,
default: undefined,
},
},
setup(props, { slots }) {
const indicator = useScrollIndicator(props.elementId)
const nuxtApp = useNuxtApp()
nuxtApp.hook('app:mounted', indicator.init)
onBeforeUnmount(() => indicator.clear())
return () =>
h(
'div',
{
class: 'nuxt-scroll-indicator-wrapper',
style: {
position: 'fixed',
zIndex: 999998,
right: 0,
left: 0,
top: 0,
pointerEvents: 'none',
height: `${props.height}px`,
background: props.background,
},
},
[
h(
'div',
{
class: 'nuxt-scroll-indicator',
style: {
height: '100%',
background: props.color,
boxShadow: props.shadow,
borderRadius: `0 ${props.borderRadius}px ${props.borderRadius}px 0`,
width: `${indicator.width.value}%`,
},
},
slots,
),
],
)
},
})
function useScrollIndicator(element?: string) {
const width = ref<number>(0)
const content = ref<number>(0)
function onScroll() {
const { documentElement, body } = document
const windowScroll
= documentElement.scrollTop - content.value || body.scrollTop
const height
= documentElement.scrollHeight
- (documentElement.clientHeight + content.value)
if (windowScroll > 0)
width.value = (windowScroll / height) * 100
else
width.value = 0
}
function init() {
if (element !== undefined) {
const elementTarget = document.getElementById(element)
const TargetTop = elementTarget?.offsetTop || 0
// TODO: Add breakpoints for mobile
content.value = TargetTop
}
window.addEventListener('scroll', onScroll)
}
function clear() {
window.removeEventListener('scroll', onScroll)
}
return {
width,
init,
clear,
}
}