VideoMarquee

Scroll a looping, draggable row of portrait video, embed, or image cards with optional controls.

VideoMarquee scrolls a looping, draggable row of portrait video, embed or image cards, with optional previous/next controls, dots and a Play/Pause toggle. It renders two copies of the card sequence in a motion track and advances it every animation frame. Cards are 18rem wide with a 9/16 aspect ratio.

Demo reel
Spring bloom
@studio
TikTok
Harbour walk
Harbour walk
@studio
Behind the scenes.
Demo reel
Close-up
@macro
TikTok
Forest trail
Forest trail
@outdoors

Import#

typescript
import { VideoMarquee } from "@reactberry/system/blocks";

Usage#

typescript
import { VideoMarquee } from "@reactberry/system/blocks";

const items = [
  { id: "reel", src: "/videos/reel.mp4", title: "Product reel", handle: "@studio" },
  { id: "tour", imageSrc: "/images/tour.jpg", title: "Studio tour", handle: "@studio", description: "Behind the scenes." },
  { id: "tiktok", embedUrl: "https://www.tiktok.com/embed/v2/1234567890", sourceUrl: "https://www.tiktok.com/@studio/video/1234567890", title: "Launch clip", handle: "@studio" },
];

export default function Showcase() {
  return <VideoMarquee items={items} speed={30} />;
}

Examples#

Without controls#

Hide the arrows, dots and toggle with showControls, showDots and showPlayPause. Here the row also scrolls to the right at a lower speed.

TikTok
Harbour walk
Harbour walk
@studio
TikTok
Forest trail
Forest trail
@outdoors
TikTok
Harbour at dusk
Harbour at dusk
@studio
TikTok
Forest path
Forest path
@outdoors

API#

VideoMarquee#

PropTypeDefaultDescription
items*
VideoMarqueeItem[]
—

Cards to render. The component returns null when empty.

speed
number
42

Auto-scroll speed in pixels per second (minimum 1).

direction
"left""right"
"left"

Auto-scroll direction.

pauseOnHover
boolean
true

Pauses auto-scroll while the pointer is over a card.

gap
string | number
1rem

Space between cards.

showControls
boolean
true

Shows previous and next controls over the track (only with more than one item).

showDots
boolean
true

Shows one dot per item; the active dot follows the scroll position.

showPlayPause
boolean
true

Shows a Play/Pause toggle for auto-scroll.

No other props are accepted and nothing is spread.

VideoMarqueeItem#

The type is exported from src/blocks/VideoMarquee but not re-exported from @reactberry/system/blocks.

PropTypeDefaultDescription
id*
string
—

Unique key for the card.

title*
string
—

Shown in bold in the caption; also used as image alt and in the iframe title.

handle*
string
—

Shown below the title.

src
string
—

Video URL, played muted, looping and inline with autoPlay.

embedUrl
string
—

Iframe URL. Takes priority over all other media fields.

imageSrc
string
—

Static image URL.

poster
string
—

Image URL, used as a static image (see Notes).

description
string
—

Optional caption text.

sourceUrl
string
—

Renders an "Open on TikTok" link that opens in a new tab.

Accessibility#

  • The duplicated sequence is aria-hidden.
  • Dots are button elements labelled "Go to demo N", and the toggle is a button with aria-pressed.
  • The previous and next controls are div elements without a button role or label, so they cannot be reached with the keyboard.
  • Auto-scroll runs on useAnimationFrame and does not check for reduced-motion preferences; the Play/Pause toggle is the only way to stop it.

Notes#

  • Media priority per card: embedUrl renders an iframe; otherwise imageSrc or poster renders an img; otherwise src renders a video. Setting poster together with src (without embedUrl) therefore shows the poster image and the video is not rendered.
  • The corner badge reads "TikTok" for embed and image cards and "Demo reel" for video cards. These labels and the "Open on TikTok" link text are fixed.
  • Auto-scroll stops when toggled off, and pauses while hovered (if pauseOnHover), while dragging, and during the 0.35 second settle animation after a control, dot, or drag.
  • The track can be dragged horizontally; on release it snaps to the nearest card. The previous and next controls move by one card width, and dots take the shortest path to their card.
  • The dots are black and the toggle is white, so the footer is meant for a light background.
  • The footer is hidden when there is only one item.