ui : fix carousel scrollability detection

Observe the content wrapper as well as the container, since adding overflowing items does not change the container's own box size. Also expose an onScrollableChange callback.

Assisted-by: pi
This commit is contained in:
Aleksander Grygier
2026-08-21 15:38:46 +02:00
committed by GitHub
parent 9bde74c881
commit 2e875fa3d5
@@ -1,7 +1,8 @@
export function useScrollCarousel() {
export function useScrollCarousel(onScrollableChange?: (isScrollable: boolean) => void) {
let canScrollLeft = $state(false);
let canScrollRight = $state(false);
let scrollContainer = $state<HTMLDivElement | undefined>();
let contentContainer = $state<HTMLDivElement | undefined>();
function scrollToCenter(element: HTMLElement) {
if (!scrollContainer) return;
@@ -34,12 +35,25 @@ export function useScrollCarousel() {
canScrollLeft = sl > 0;
canScrollRight = sl < scrollWidth - clientWidth - 1;
onScrollableChange?.(scrollWidth > clientWidth);
}
// Re-evaluate arrow visibility whenever the container or its content resizes,
// otherwise the arrows may not appear when overflowing items are added (e.g. new
// tabs/attachments) and the user has not scrolled yet.
$effect(() => {
if (scrollContainer) {
updateScrollButtons();
}
if (!scrollContainer) return;
updateScrollButtons();
const observer = new ResizeObserver(() => updateScrollButtons());
observer.observe(scrollContainer);
if (contentContainer) observer.observe(contentContainer);
return () => observer.disconnect();
});
return {
@@ -49,6 +63,12 @@ export function useScrollCarousel() {
get canScrollRight() {
return canScrollRight;
},
get contentContainer() {
return contentContainer;
},
set contentContainer(el: HTMLDivElement | undefined) {
contentContainer = el;
},
get scrollContainer() {
return scrollContainer;
},