Skip to content

ol-carousel touch gestures and swipe physic refinements#13101

Open
lokesh wants to merge 5 commits into
internetarchive:masterfrom
lokesh:ol-carousel-refinements
Open

ol-carousel touch gestures and swipe physic refinements#13101
lokesh wants to merge 5 commits into
internetarchive:masterfrom
lokesh:ol-carousel-refinements

Conversation

@lokesh

@lokesh lokesh commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Follow-up polish to #13077 (no linked issue).

Low risk: <ol-carousel> is not used on any live page yet — it only appears in the design showcase (/developers/design#carousel). Nothing user-facing changes.

This refines how the carousel feels to use — mostly around touch and swiping.

carousel.mp4

Swiping feels right now

  • Scrolling the page vertically no longer accidentally flips a carousel page, and swiping the carousel sideways no longer jitters the page up and down.
  • Diagonal swipes still catch the carousel instead of losing out to page scroll.
  • A long drag can travel across several pages and land on the nearest one, instead of snapping back.
  • Momentum on release is smoother — no surprise flings after you pause mid-drag.

Covers are ready before you get there

  • The next page's covers start loading the moment you hover or tab into a carousel, so they're already there when you reach them. Skipped on data-saver / slow connections so it never wastes mobile data.

Keyboard

  • Page indicators are arrow-key navigable (←/→, Home, End).

Testing

  1. Open /developers/design#carousel (use Chrome device mode for touch).
  2. Swipe left/right — the page shouldn't scroll during the swipe, and angled swipes should still move the carousel.
  3. Swipe repeatedly, including right after a page transition.
  4. Hover or tab into a carousel — the next page's covers should load ahead.
  5. With indicators shown, use ←/→/Home/End to move between pages.

Covered by 18 tests in tests/unit/js/OlCarousel.test.js.

Stakeholders

@RayBB

Touch swipes were unreliable: starting a vertical page scroll on the
carousel could fire a page navigation (pointercancel was handled as a
release), horizontal swipes scrolled the page underneath, and after the
first page transition the swipe surface went dead on iOS (the
pointerdown listener lived on the translated track).

- Resolve gesture ownership with an axis lock (8px dead zone, 2:1
  horizontal bias) and preventDefault page scroll once locked
- Treat pointercancel as an abort that springs home, never a navigation
- Move gesture listeners to the untransformed viewport so the whole
  surface stays swipeable on every page
- Smooth velocity (EMA over >=4ms windows, capped, stale samples
  discarded) so release momentum is stable
- Land long drags on the nearest page; momentum carries at most one
  page beyond it

Adds a jest suite covering the gesture state machine.
@lokesh
lokesh marked this pull request as ready for review July 6, 2026 19:43
@lokesh lokesh changed the title Fix ol-carousel touch gestures and refine swipe physics ol-carousel touch gestures and swipe physic refinements Jul 10, 2026
ol-carousel refinements:
- Deepen the cover lookahead from one page to two on the first hover or
  keyboard focus, so fast page-flipping stays ahead of the loaded range.
  Skipped on data-saver / 2g connections; fires at most once.
- Add arrow-key / Home / End navigation to the page-indicator tablist
  with a roving tabindex (APG Tabs pattern), plus tests.
- Regenerate custom-elements.json to match.
@lokesh

lokesh commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

@cdrini take a look when you get the chance.

Add discrete wheel-based paging: a horizontal trackpad swipe (wheel
events with deltaX) flips one page per gesture, reusing the existing
spring. Only claims horizontal-dominant intent, so vertical scroll and
plain mouse wheels pass through; preventDefault owns the gesture and
suppresses macOS history back/forward swipe. Momentum tail is swallowed
so one physical swipe pages once.

Adds 7 unit tests covering direction, vertical pass-through, threshold,
momentum lock, gesture-end re-arm, and line-mode normalization.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants