Skip to main content

ProductVideos

Renders product videos as embedded players (YouTube, Vimeo) or native HTML5 <video> elements. Automatically detects the video platform from the URI and converts it to an embeddable format. Resolves localized video URIs and titles based on the provided language code.


Usage

Basic usage on a product detail page

import ProductVideos from '@/components/propeller/ProductVideos';

<ProductVideos
videos={product.media.videos}
language="EN"
/>

With custom labels

<ProductVideos
videos={product.media.videos}
language="NL"
labels={{
title: 'Productvideo\'s',
empty: 'Geen video\'s beschikbaar',
}}
/>

With custom styling

<ProductVideos
videos={product.media.videos}
language="EN"
className="mt-6 max-w-2xl"
/>

Conditionally rendering only when videos exist

{product.media?.videos?.items?.length > 0 && (
<ProductVideos
videos={product.media.videos}
language="EN"
labels={{ title: 'Watch' }}
/>
)}

Inside a tabbed product detail layout

<Tabs>
<Tab label="Description">
<ProductDescription ... />
</Tab>
<Tab label="Videos">
<ProductVideos
videos={product.media.videos}
language={currentLanguage}
/>
</Tab>
</Tabs>

Configuration

Required

PropTypeDescription
videosPaginatedMediaVideoResponseThe video media object from the product. Pass product.media.videos directly.
languagestringTwo-letter language code (e.g. "EN", "NL") used to resolve the correct localized video URI and title. Falls back to "NL" when empty.

Optional — Appearance

PropTypeDefaultDescription
classNamestringundefinedAdditional CSS class applied to the root <div>.

Optional — Labels

PropTypeDefaultDescription
labelsRecord<string, string>undefinedOverride UI strings. Supported keys: title (heading above the video list, default "Videos"), empty (message when no videos exist, default "No videos").

Labels

KeyDefaultDescription
title"Videos"Heading above the video list
empty"No videos"Message when no videos exist

Behavior

Platform detection and embedding

The component inspects each video URI to determine how to render it:

PlatformURL patterns detectedRendered as
YouTubeyoutube.com/watch?v=..., youtu.be/...<iframe> pointing to youtube.com/embed/{id}
Vimeovimeo.com/{id}<iframe> pointing to player.vimeo.com/video/{id}
Other (self-hosted, CDN)Any URI not matching aboveNative <video> element with controls

Embedded iframes use a 16:9 aspect ratio (padding-bottom: 56.25%) and load lazily. They allow accelerometer, autoplay, clipboard-write, encrypted-media, gyroscope, and picture-in-picture permissions.

Native video players use preload="metadata" to avoid downloading full video files until the user hits play.

Empty state

When videos.items is empty or not provided, the component renders a muted text message (default: "No videos"). The heading is hidden in this case.

Rendering order

Videos are rendered in the same order they appear in the items array. Each video is wrapped in a rounded, bordered container with a black background.


GraphQL Query Example

When fetching a product, include the media.videos field to supply data to this component:

query GetProduct($productId: Int!, $language: String) {
product(id: $productId, language: $language) {
productId
name {
language
value
}
media {
videos {
items {
videos {
language
uri
}
alt {
language
value
}
}
}
}
}
}

SDK Services

This component does not call any SDK service directly. It is a presentational component that receives data through its videos prop.

Product fields consumed

The videos prop expects the PaginatedMediaVideoResponse type, which is found at product.media.videos. The component reads the following nested fields:

Field pathTypePurpose
videos.itemsMediaVideo[]The list of video entries to render.
videos.items[].videosLocalizedVideo[]Localized video URIs. Each entry has language (string) and uri (string).
videos.items[].altLocalizedString[]Localized alt text / titles. Each entry has language (string) and value (string).

Language resolution

For both URIs and titles, the component:

  1. Searches the localized array for an entry matching the language prop.
  2. Falls back to the first entry in the array if no match is found.
  3. Falls back to an empty string (URI) or "Video" (title) if the array is empty.