diff --git a/packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue b/packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue index f066b91a..e101ba59 100644 --- a/packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue +++ b/packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue @@ -39,6 +39,14 @@ const isAtRight = ref(false); const isAtBottom = ref(false); const isAtLeft = ref(true); +/** + * We have to check if the scroll amount is close enough to some threshold in order to + * more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded + * numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded. + * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled + */ +const ARRIVED_STATE_THRESHOLD_PIXELS = 1; + const showShadowTop = computed(() => props.shadow && props.shadowTop); const showShadowBottom = computed(() => props.shadow && props.shadowBottom); const showShadowLeft = computed(() => props.shadow && props.shadowLeft); @@ -60,14 +68,18 @@ function handleScroll(event: Event) { const target = event.target as HTMLElement; const scrollTop = target?.scrollTop ?? 0; const scrollLeft = target?.scrollLeft ?? 0; - const offsetHeight = target?.offsetHeight ?? 0; - const offsetWidth = target?.offsetWidth ?? 0; + const clientHeight = target?.clientHeight ?? 0; + const clientWidth = target?.clientWidth ?? 0; const scrollHeight = target?.scrollHeight ?? 0; const scrollWidth = target?.scrollWidth ?? 0; isAtTop.value = scrollTop <= 0; isAtLeft.value = scrollLeft <= 0; - isAtBottom.value = scrollTop + offsetHeight >= scrollHeight; - isAtRight.value = scrollLeft + offsetWidth >= scrollWidth; + isAtBottom.value = + Math.abs(scrollTop) + clientHeight >= + scrollHeight - ARRIVED_STATE_THRESHOLD_PIXELS; + isAtRight.value = + Math.abs(scrollLeft) + clientWidth >= + scrollWidth - ARRIVED_STATE_THRESHOLD_PIXELS; emit('scrollAt', { bottom: isAtBottom.value,