Skip to content

Instantly share code, notes, and snippets.

@iamandrewluca
Last active May 9, 2023 20:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamandrewluca/5677fcb74d1215a89652c916fd3af5af to your computer and use it in GitHub Desktop.
Save iamandrewluca/5677fcb74d1215a89652c916fd3af5af to your computer and use it in GitHub Desktop.
<template>
<component :is="tag" class="relative">
<button
:class="[
'absolute top-0 h-full w-10 left-0 bg-gradient-to-r to-transparent',
startColor,
]"
:style="{ opacity: leftOpacity }"
@click="elementRef?.scrollBy({ left: -200, behavior: 'smooth' })"
/>
<div ref="elementRef" class="overflow-y-auto">
<slot />
</div>
<button
:class="[
'absolute top-0 h-full w-10 right-0 bg-gradient-to-l to-transparent',
startColor,
]"
:style="{ opacity: rightOpacity }"
@click="elementRef?.scrollBy({ left: 200, behavior: 'smooth' })"
/>
</component>
</template>
<script setup lang="ts">
import { useThrottleFn } from '@vueuse/core';
import { onMounted, onUnmounted, ref } from 'vue';
defineProps({
tag: {
type: String,
default: 'div',
},
startColor: {
type: String,
default: 'from-gray-200',
},
});
const resizeObserver = ref<ResizeObserver>();
const elementRef = ref<HTMLElement>();
const leftOpacity = ref(0);
const rightOpacity = ref(0);
const throttledAdjust = useThrottleFn(function adjust() {
if (!elementRef.value) return;
const { scrollLeft, scrollWidth, clientWidth } = elementRef.value;
const nonVisibleSize = scrollWidth - clientWidth;
const scrollPercent = Math.floor((scrollLeft * 100) / nonVisibleSize) / 100;
leftOpacity.value = nonVisibleSize === 0 ? 0 : scrollPercent;
rightOpacity.value = nonVisibleSize === 0 ? 0 : 1 - scrollPercent;
}, 60);
onMounted(() => {
throttledAdjust();
elementRef.value?.addEventListener('scroll', throttledAdjust);
resizeObserver.value = new ResizeObserver(throttledAdjust);
resizeObserver.value?.observe(elementRef.value?.parentElement!);
});
onUnmounted(() => {
elementRef.value?.removeEventListener('scroll', throttledAdjust);
resizeObserver.value?.disconnect();
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment