Skip to main content
A video carousel is a horizontally-swipeable collection of short videos within a single feed cell. The SDK owns the pager, the player handoff between pages, and the transition animations natively. This page covers the APIs you use to observe the active carousel, navigate it programmatically, and react to video completions. To render the chrome (titles, page indicators, action buttons) on top of the native pager, see Overlays › Video carousel overlays. For the VideoCarouselItem data shape, see Content Types › Video carousel.

Default behavior

When the current feed item is a video carousel, the SDK applies these rules automatically — no configuration required.

Programmatic navigation

Imperative methods move the active carousel without a user gesture. All three return a boolean indicating whether the command was accepted. These methods are scoped to the current carousel — they page between videos inside a single VideoCarouselItem. They are distinct from the feed-scoped shortKit.player.skipToNext() / ShortKitCommands.skipToNext(), which navigate between feed items (including across carousels).
Declarative landing vs. imperative jump. setActiveIndex(_:) is for moving within an already-active carousel — for example, in response to a button tap inside an overlay. To land on a specific page on the first display (deep-linking, e.g. a “watch from video 3” CTA), set initialPageIndex on the VideoCarouselItem instead. The declarative path lands without a horizontal scroll animation; setActiveIndex only operates on the active cell and produces an animated scroll.
Access the carousel API via shortKit.carousel. Methods are safe to call from any thread; they hop to the main queue internally.
All three methods are marked @discardableResult, so you can ignore the return value for fire-and-forget usage:

Return value

setActiveIndex(_:) with the current index returns true as a no-op.

Observing active state

Subscribe to reactive state to keep overlay UI, badges, or host-app chrome in sync with the active carousel.
ShortKit exposes Combine publishers on shortKit.carousel. Always dispatch to the main queue with .receive(on: DispatchQueue.main) before updating UI.Example:
For one-off synchronous reads, use:

Cell gesture events

Two events fire on direct user interaction with a video-carousel cell:
  • onVideoCarouselCellTap — a discrete tap that didn’t turn into a horizontal pan.
  • onVideoCarouselCellLongPress — the lifecycle of a sustained press.
Both are passive observers on the cell. They run alongside the carousel’s horizontal pan and the feed’s vertical pan without intercepting either, so a press that becomes a horizontal swipe still pages the carousel, and a press that becomes a vertical swipe still advances the feed. Use these for analytics, custom interactions like double-tap-to-like, or hold-to-pause UX.

Tap

Fires once per discrete tap on a carousel cell that did not trigger the inner horizontal pan. Quick taps qualify; presses that turn into pans do not.
Set the closure on your ShortKitFeedViewController instance.

Long press

Available since SDK 0.2.36.
Fires across the lifecycle of a sustained press: a began after 0.2s of continuous touch within 10 points of the touch origin, then exactly one terminal state — ended on touch release, or cancelled if the press is interrupted.

Lifecycle states

Every press that reaches began is followed by exactly one terminal state — ended or cancelled. Touches that don’t satisfy the recognizer (released before 0.2s, or moved >10 points before 0.2s) never fire any long-press event. Use state === 'began' to start an effect (pause, dim, show menu) and treat both ended and cancelled as the signal to undo it.

Recipe: hold-to-pause

A common use is letting the user pause playback by holding the cell — a familiar pattern in short-video feeds.
Because the recognizer is a passive observer, a hold that turns into a horizontal swipe still pages the carousel — the cancelled arm of the switch is what restores playback when that happens.
This minimal recipe will resume playback after a hold even if the user had manually paused the video before holding. To preserve manual pauses, track the player state and only call play() from the ended/cancelled arm if the video was playing before began fired.

Completion events

A completion event fires each time a carousel video reaches its natural end — after playback, not on skip. Use it for analytics, end-of-carousel CTAs, or host-level auto-advance behavior that extends what the SDK does by default.
Subscribe to the activeVideoCompleted publisher on shortKit.carousel. It emits a CarouselCompletionEvent per natural end.

CarouselCompletionEvent

Event field reference

The event fires only on natural end-of-playback. It does not fire when:
  • The user swipes to a different video in the carousel.
  • Your code calls next(), previous(), or setActiveIndex(_:).
  • The feed navigates vertically (by swipe or programmatically) to a different feed item.
A common use case is showing a “Read the full article” or “Subscribe” card after the user has watched every video in a carousel. Because the last video loops by default (rather than spilling into the next feed item), your host app is in full control of what happens next.
The wasLast && !willAutoAdvance check is the idiomatic “user reached the end of the carousel” signal. Because the video keeps looping silently underneath, you can display the CTA without worrying about playback changing out from under you — the user is either watching the last video loop or is about to swipe away.