Skip to content

feat: Carousel autoplay#361

Merged
hcopp merged 41 commits intomasterfrom
hunter/carousel-autoplay
Feb 6, 2026
Merged

feat: Carousel autoplay#361
hcopp merged 41 commits intomasterfrom
hunter/carousel-autoplay

Conversation

@hcopp
Copy link
Contributor

@hcopp hcopp commented Feb 3, 2026

What changed? Why?

This PR

  • Adds Carousel autoplay
  • Adds paginationVariant to Carousel, to support the new design
  • Improves web Carousel accessibility

Root cause (required for bugfixes)

Minor bug fixes

  • Removes duplicate a11y prop on mobile (goToPageAccessibilityLabel) that was not found used in code and was broken
  • Pagination buttons are no longer sized based on spacing tokens (were too small in dense themes)

UI changes

Mobile

With autoplay, we show the progress of the interval inside the new pagination variant

Web

image

With autoplay, we show the progress of the interval inside the new pagination variant

image

Testing

How has it been tested?

  • Unit tests
  • Interaction tests
  • Pseudo State tests
  • Manual - Web
  • Manual - Android (Emulator / Device)
  • Manual - iOS (Emulator / Device)

Testing instructions

Test out doc site examples and storybook for web and mobile.

Illustrations/Icons Checklist

Required if this PR changes files under packages/illustrations/** or packages/icons/**

  • verified visreg changes with Terran (include link to visreg run/approval)
  • all illustration/icons names have been reviewed by Dom and/or Terran

Change management

type=routine
risk=low
impact=sev5

automerge=false

@cb-heimdall
Copy link
Collaborator

cb-heimdall commented Feb 3, 2026

✅ Heimdall Review Status

Requirement Status More Info
Reviews 1/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 1
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1
CODEOWNERS ✅ See below

CODEOWNERS

Code Owner Status Calculation
ui-systems-eng-team 1/1
Denominator calculation
Additional CODEOWNERS Requirement
Show calculation
Sum 0
0
From CODEOWNERS 1
Sum 1

* Callback fired when autoplay stops.
*/
onStop?: () => void;
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious what y'all think about having an api for this. It felt like a hook was best given all the unique logic just for autoplay, and storing it in common helps reuse, similar to useStepper. But I'm open to ideas.

throw new Error('useCarouselAutoplayContext must be used within a Carousel component');
}
return context;
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My logic for keeping this separate vs CarouselContext is

A) CarouselContext wasn't meant to be used by consumers, only for CarouselItem
B) Autoplay could be triggering updates a lot

* When a function is provided, it receives the page index and returns a label.
* @default (pageIndex) => `Go to page ${pageIndex + 1}`
*/
goToPageAccessibilityLabel?: string;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goToPageAccessibilityLabel was a bug on mobile, we already supported paginationAccessibilityLabel - which is what we meant to use and is how it works on web. I checked and found no uses of this, but am fine if others want me to mark it as deprecated.

background={isActive ? 'bgPrimary' : 'bgLine'}
borderColor="transparent"
data-active={isActive}
tabIndex={isActive ? undefined : -1}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are dropping tabs accessibility experience here since it wasn't properly/fully implemented. Confirmed with design that doing buttons is also more likely what users will expect here.

// Handle focus moving to an element inside the carousel items container.
// Pauses autoplay when focus enters from outside (keyboard navigation a11y).
// Scrolls to show focused items that are not fully visible.
const handleFocusIn = useCallback(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greatly improved accessibility here, users will be able to navigate through carousel items by tabbing. Before, they could only tab to items within view, and needed to use navigation or pagination buttons to switch between pages.

This functionality ignores clones from looping as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still syncing with Sam to see if we should change mobile.

adrienzheng-cb
adrienzheng-cb previously approved these changes Feb 5, 2026
adrienzheng-cb
adrienzheng-cb previously approved these changes Feb 6, 2026
adrienzheng-cb
adrienzheng-cb previously approved these changes Feb 6, 2026
@hcopp hcopp merged commit 992a591 into master Feb 6, 2026
28 checks passed
@hcopp hcopp deleted the hunter/carousel-autoplay branch February 6, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants