Playlist
A queue of videos, with previous and next buttons and an up-next card.
import { playlist } from "react-video-kit/playlist";Adds 1.3 KB to a player2.6 KB on its ownSource
Adds previous and next buttons to the controls, and a card offering the next video when one ends. Press Next below, or seek close to the end and wait for the card. It counts down from 3 here, then plays the next item.
"use client";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";import { playlist } from "react-video-kit/playlist";const items = [ { src: "/media/sample-360.mp4", title: "First light", poster: "/media/poster.jpg" }, { src: "/media/sample-270.mp4", title: "The long ridge" }, { src: "/media/sample-720.mp4", title: "Last light" },];const plugins = [playlist({ items, countdown: 3 }), ...defaultPlugins()];export default function Playlist() { return <VideoPlayer plugins={plugins} load="visible" />;}Usage
Give the plugin items, and leave src off the player:
import { VideoPlayer } from "react-video-kit/player";import { playlist } from "react-video-kit/playlist";const plugins = [ playlist({ items: [ { src: "/first.mp4", title: "First light", poster: "/first.jpg" }, { src: "/second.mp4", title: "The long ridge" }, ], }),];<VideoPlayer plugins={plugins} />;An item's src takes anything the player's src does, such as a list of fallbacks.
An item's title, eyebrow, and description show above the timeline while it plays, as they would on the player. To browse the queue by season, with thumbnails and running times, add the episodes plugin.
Use start to begin on another item, and loop to wrap around at the ends:
playlist({ items, start: 2, loop: true });countdown sets how many seconds the up-next card counts down, and defaults to 5. 0 skips the card and moves on at once. null shows the card and waits for the viewer.
playlist({ items, countdown: null });Show the queue
Read the queue with useVideoState and move through it with useCommands, from anywhere inside the player.
"use client";import { useCommands, useVideoState } from "react-video-kit";import { playlist } from "react-video-kit/playlist";function Queue() { const items = useVideoState(playlist, (state) => state.items); const index = useVideoState(playlist, (state) => state.index); const { select } = useCommands(playlist); return ( <ol> {items.map((item, position) => ( <li key={position}> <button aria-current={position === index} onClick={() => select(position)}> {item.title} </button> </li> ))} </ol> );}select plays straight away. select(position, false) loads the item without playing. setItems replaces the queue and loads the item at the index you give it, also without playing.
Place the parts yourself
VideoPlayer places the buttons and the card through slots. When you compose your own layout, put them wherever you like:
import * as Video from "react-video-kit";import { PlaylistNext, PlaylistPrevious, PlaylistTitle, UpNext } from "react-video-kit/playlist";<Video.Root plugins={plugins}> <Video.Media /> <UpNext /> <Video.Controls> <PlaylistTitle /> <PlaylistPrevious /> <Video.PlayPause /> <PlaylistNext /> </Video.Controls></Video.Root>;Behaviour
- The queue decides what plays. The current item replaces any
srcon the player when it mounts. - Every item plays in the same
<video>element, andnext,previous, andselectask it to play in the same tick. A new element wouldn't have permission to autoplay on mobile. - Without
loop,nextdoes nothing on the last item andpreviousdoes nothing on the first. The matching button getsaria-disabled, and no card appears when the last item ends. - With
loop, both buttons stay enabled.nexton the last item goes to the first,previouson the first goes to the last, and the last item's card offers the first. - With a single item, the buttons don't render.
- Play now moves on straight away, and Cancel stays on the finished video. Seeking back or replaying clears the card too, because the video is no longer ended.
- An item with no
posterremoves the poster, including one set on the player. - An item's
titleappears on the up-next card. With no title, the card leaves that line out. - A
title,eyebrow, ordescriptiononVideoPlayerreplaces the current item's, so nothing changes as the queue moves. - The root has
data-up-nextwhile the card is showing. - The persistence plugin saves a position for each item, so going back to an item resumes it.
- The media session plugin doesn't register previous or next track actions, so the system's track buttons don't move through the queue.
API
Options
| Option | Type | Description |
|---|---|---|
| items | readonly PlaylistItem[] | The videos in the queue, in play order. |
| start? | number | The item to start on. |
| loop? | boolean | Go back to the first item after the last. |
| countdown? | number | null | Seconds the up-next card counts down. 0 moves on at once, null waits for the viewer. |
State
Read it with useVideoState(playlist, (state) => …).
| Field | Type | Description |
|---|---|---|
| items | readonly PlaylistItem[] | The videos in the queue. |
| index | number | Position of the current item in items. |
| loop | boolean | True when the queue wraps around at both ends. |
| remaining | number | null | Seconds until the next item, while counting down. |
| upNext | boolean | Whether the viewer can see what's next, even with no countdown running. |
Commands
Call them with useCommands(playlist).
| Command | Type | Description |
|---|---|---|
| select | (index: number, play?: boolean) => void | Moves to the item at this index and plays it, unless play is false. |
| next | () => void | Moves to the next item and plays it, wrapping around if loop is on. |
| previous | () => void | Moves to the previous item and plays it, wrapping around if loop is on. |
| cancel | () => void | Stays on the finished video. |
| setItems | (items: readonly PlaylistItem[], index?: number) => void | Replaces the queue, starting from index. |
| nextIndex | () => number | null | The next item's position, or null at the end. |
Parts
| Part | Description |
|---|---|
| PlaylistNext | Hidden with a single item. Disabled at the end, unless looping wraps it around. |
| PlaylistPrevious | Hidden with a single item. Disabled at the start, unless looping wraps it around. |
| PlaylistTitle | The current item's title, eyebrow, and description. Hidden when it has none of them. |
| UpNext | Offers the next item when one finishes, counting down if configured to. |