feat(carousel): add hasLoop wrap-around and handleRef imperative control - #4629
Open
freddymeta wants to merge 1 commit into
Open
feat(carousel): add hasLoop wrap-around and handleRef imperative control#4629freddymeta wants to merge 1 commit into
freddymeta wants to merge 1 commit into
Conversation
Add two capabilities to the native-scroll Carousel: - hasLoop: wrap-around scrolling. Next at the end returns to the start and prev at the start jumps to the end, for both the built-in buttons and the imperative handle. Navigation buttons stay active at both edges. Only engages when the content overflows. - handleRef: an imperative handle (CarouselHandle) exposing scrollNext, scrollPrev, scrollTo(index), canScrollNext() and canScrollPrev() for programmatic control, following the established handleRef convention. Both are re-expressed in terms of the existing native-scroll machinery (scrollBy + useScrollOverflow), so no scroll engine is introduced. RTL and reduced-motion behavior is inherited from the existing scroll logic.
freddymeta
requested review from
cixzhang,
ejhammond and
imdreamrunner
as code owners
August 1, 2026 06:30
github-actions
Bot
requested review from
cvkxx,
ernestt,
kentonquatman and
rubyycheung
August 1, 2026 06:30
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
PR Analysis Report📚 Storybook PreviewView Storybook for this PR 🧪 Sandbox PreviewView Sandbox for this PR Modified ComponentsCarousel (@astryxdesign/core) · View in Storybook
Bundle Size Summary
Accessibility AuditStatus: No accessibility violations detected. Generated by PR Enrichment workflow | Storybook | Sandbox | View full report |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds two capabilities to
Carousel, both re-expressed in terms of its existing native-scroll machinery (no scroll engine introduced):hasLoop?: boolean(defaultfalse)Wrap-around scrolling. Pressing Next at the end returns to the start, and Prev at the start jumps to the end — for both the built-in navigation buttons and the imperative handle. The buttons stay active at both edges instead of hiding, since a scroll is always available. Only engages when the content actually overflows (a single-screen carousel is a no-op).
handleRef?: React.Ref<CarouselHandle>An imperative handle for programmatic scroll control, following the established
handleRef+{Name}Handleconvention used byTokenizer,Calendar,PowerSearch, and others (keeps the DOMrefintact).Design notes
hasLoopimplements bounded wrap-around by overshooting toward the opposite edge and letting the browser clamp — the honest native-scroll equivalent of a looping carousel. Clone-based seamless infinite scrolling is intentionally out of scope; the prop is forward-compatible with a future'infinite'mode if it's ever needed.canScroll*are methods, not getters. Matching how other handles expose reads (getValue(),getCollapseState()), they read live overflow state so callers can query them from an event handler.scrollTo(index)stays contained. It scrolls the carousel container by a measured delta rather than callingscrollIntoView, so it never moves ancestors or the page. RTL-aware.prefers-reduced-motionbehavior is inherited from the existing scroll logic.Testing
packages/core/src/Carousel/Carousel.test.tsx: 23 tests pass (7 new — loop wrap-around both directions, buttons stay enabled at edges under loop, no-wrap when content fits, handle scrollNext/Prev/scrollTo, livecanScroll*, loop reachability).