Saltar al contenido principal

Video Stories

The VideoStories component is a vertical, stories-style player for a sequence of self-hosted videos (MP4, HLS, DASH) — the Instagram/WhatsApp stories pattern. It renders inline as a compact 9:16 card that can be expanded into a fullscreen overlay, with a segmented progress bar, tap navigation, hold-to-pause and a mute toggle.

Unlike Video , which plays a single video, VideoStories owns a playlist: it advances between stories on its own, entirely on the storefront, without a round trip to your app.

Video Stories

The chrome is drawn by the component itself: one progress segment per story along the top, the mute toggle on the left and the expand button on the right.

Lazy loading
The underlying playback engine is only downloaded the first time a video is rendered on the page, so adding the component doesn't increase the initial size of your app.

Usage

Pass an ordered list of stories through items. Each item is a video src with an optional poster image shown before playback starts.

Basic playlist
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { VideoStories } from "@tiendanube/nube-sdk-jsx";

function MyComponent() {
return (
<VideoStories
width={220}
items={[
{
src: "https://cdn.example.com/story-1.mp4",
poster: "https://cdn.example.com/story-1.jpg",
},
{
src: "https://cdn.example.com/story-2.mp4",
poster: "https://cdn.example.com/story-2.jpg",
},
]}
/>
);
}

export function App(nube: NubeSDK) {
nube.render("after_product_description", <MyComponent />);
}

Inline card and fullscreen overlay

The component has two presentations, and only one of them is playing at any time:

  • Inline card — a 9:16 card rendered in the flow of the slot, sized by width. It autoplays muted, but only while at least half of the card is on screen, so several stories on the same page don't all start decoding at once.
  • Fullscreen overlay — opened with the expand button in the corner of the card. It covers the viewport, locks page scrolling, and is closed with the close button or the Esc key.

Tapping the video itself does not open the overlay — only the expand button does, which keeps side taps free for navigation. Playback is carried across the transition: expanding resumes at the moment the inline card had reached, and closing resumes the card where the overlay left off.

Playback options

Looping playlist that starts with sound off
<VideoStories
items={items}
width="100%"
startMuted
autoAdvance
loop
/>
  • startMuted (default true) — starts muted, as browsers require for autoplay. The viewer can unmute with the mute button, and that choice is kept as the playlist advances.
  • autoAdvance (default true) — moves to the next story when the current one ends. With false, playback stops on the last frame of each story and only explicit navigation moves on: a side tap (when tapToNavigate is on) or, in the fullscreen overlay, the and keys.
  • loop (default false) — restarts from the first story after the last one instead of finishing. It only has an effect together with autoAdvance.

When the playlist reaches the end and loop is false, the component emits onComplete, closes the overlay if it was open, rewinds to the first story and holds it paused — so it neither loops nor sits on a frozen final frame. The next interaction (expanding or a navigation tap) starts it again from the top.

  • Tap navigation (tapToNavigate, default true) — tapping the left third goes to the previous story, the right third to the next one. Works both inline and fullscreen.
  • Hold to pause (pauseOnHold, default true) — pressing and holding pauses the story; releasing resumes it. A hold never also navigates.
  • Keyboard — while the overlay is open, and move between stories andEsc closes it. Arrow keys are ignored while a form control is focused.
  • Progress bar — one segment per story, with the active segment filling as the story plays.

Overlay content

Children passed to VideoStories are rendered as an overlay on top of the active story, in both the inline card and the fullscreen overlay. This is where calls to action, captions or product links go.

Call to action over the story
<VideoStories items={items} width={220}>
<Text style={{ position: "absolute", bottom: "24px", left: "12px", color: "#fff" }}>
Shop the look
</Text>
</VideoStories>

Events

Every handler receives an object with type, the current SDK state, and a value payload. These events are observe-only: they report what the player did and never gate or alter playback.

Eventvalue payloadDescription
onOpen{ index: number, total: number }Fired when the fullscreen overlay opens, with the active story and playlist size.
onClose{ index: number }Fired when the fullscreen overlay closes.
onChange{ index: number }Fired when the active story changes, by auto-advance or by navigation.
onComplete{ total: number }Fired when the playlist moves past the last story (never fired when loop is true).
onError{ index: number }Fired when a story fails to load or play.
Tracking story engagement
<VideoStories
items={items}
onOpen={({ value }) => console.log(`opened at ${value.index} of ${value.total}`)}
onChange={({ value }) => console.log("now showing", value.index)}
onClose={({ value }) => console.log("closed at", value.index)}
onComplete={({ value }) => console.log(`watched all ${value.total} stories`)}
onError={({ value }) => console.error("story failed:", value.index)}
/>

When a story fails and autoAdvance is on, the player skips to the next one after emitting onError. If every remaining source is broken it stops advancing instead of cycling through the playlist forever.

Properties

PropertyTypeRequiredDescription
itemsVideoStoriesItem[]YesThe ordered playlist. Each item is { src, poster? } with absolute HTTPS URLs.
widthnumber | stringNoWidth of the inline 9:16 card (e.g. 220, "100%"). Defaults to "100%".
startMutedbooleanNoStart muted. Defaults to true, as required by browser autoplay policies.
autoAdvancebooleanNoAdvance to the next story when the current one ends. Defaults to true.
loopbooleanNoRestart from the first story after the last one. Defaults to false.
tapToNavigatebooleanNoTap the left/right thirds to change story. Defaults to true.
pauseOnHoldbooleanNoPress and hold to pause, release to resume. Defaults to true.
childrenNubeChildrenComponentNoOverlay content rendered on top of the active story.
onOpen(event) => voidNoCalled when the fullscreen overlay opens.
onClose(event) => voidNoCalled when the fullscreen overlay closes.
onChange(event) => voidNoCalled when the active story changes.
onComplete(event) => voidNoCalled when the last story finishes.
onError(event) => voidNoCalled when a story fails to load or play.
styleStyleSheetNoCustom styles for the inline card container.
idstringNoOptional unique identifier for the component.

VideoStoriesItem

PropertyTypeRequiredDescription
srcstringYesAbsolute HTTPS URL of an MP4, HLS (.m3u8) or DASH (.mpd) video.
posterstringNoAbsolute HTTPS URL of a poster image shown before playback.

Help us improve NubeSDK

Found an issue or have a suggestion? Let us know on GitHub.