diff --git a/tools/ui/src/lib/hooks/use-scroll-carousel.svelte.ts b/tools/ui/src/lib/hooks/use-scroll-carousel.svelte.ts index d23b8536b8..9d1043d8bf 100644 --- a/tools/ui/src/lib/hooks/use-scroll-carousel.svelte.ts +++ b/tools/ui/src/lib/hooks/use-scroll-carousel.svelte.ts @@ -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(); + let contentContainer = $state(); 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; },