Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.17.0 · main

Video

tier 2 — classes

A frame around the platform's own player, and a video as a tile in a grid. The <video controls> stays native — play, seek, volume, captions, full screen and the keyboard are the browser's and none of it is redrawn. The library adds what the element does not carry: the title, the length, the actions and the transcript. Sound on its own is Audio.

The demos have no video in them This site loads photographs from one remote host and nothing else, so each player shows its poster and has no source. The package loads nothing remote; the app's <source> and <track> go inside the element.

A player

.media-player is a <figure>: the <video> on a black letterbox at 16:9 before a byte has loaded, so the page does not jump when the metadata arrives, then the .media-player-body as its caption — the .media-player-title and a .file-meta line in .media-player-text, and .media-player-actions. Give the element its width, height and a poster, and preload="metadata" or "none" in a page of several.

Captions are a <track kind="captions">, which is what puts the captions button in the native controls; a toggle of your own beside the title is a button with aria-pressed that sets the track's mode. .media-transcript is the same words under the player, readable and searchable without playing: a <details>, so it opens with no script, holding an <ol> of lines. Each .media-transcript-time is a button the app wires to currentTime, and the line being spoken carries aria-current="true", set from the element's timeupdate.

Receiving a pallet at dock 4 4:32Alex Fischer
Transcript
  1. Before the truck backs in, check the dock plate is down and the bay light is green.
  2. Scan the delivery note first, not the pallet — the note is what the order is matched against.
  3. Count the cartons on the outside layer and compare with the quantity on the note.
  4. Anything crushed or wet gets a photo before the wrap comes off.
  5. Sign on the scanner, and the note is filed against the order on its own.

The poster is a photograph by Ruchindra Gunasekara on Unsplash. The demo has no source: the app's <source> and <track kind="captions"> go inside the <video>.

<figure class="media-player" style="max-width:640px">
    <video controls preload="none" width="1280" height="720"
           poster="https://images.unsplash.com/photo-1553413077-190dd305871c?w=1280&amp;h=720&amp;fit=crop&amp;q=70&amp;auto=format"
           aria-label="Receiving a pallet at dock 4">
    </video>
    <figcaption class="media-player-body">
        <span class="media-player-text">
            <strong class="media-player-title">Receiving a pallet at dock 4</strong>
            <span class="file-meta"><span>4:32</span><time datetime="2026-09-12">12 Sep 2026</time><span>Alex Fischer</span></span>
        </span>
        <span class="media-player-actions">
            <button class="btn btn-ghost btn-icon btn-sm" type="button" aria-pressed="true" aria-label="Captions"><i class="ri-closed-captioning-line"></i></button>
            <a class="btn btn-ghost btn-icon btn-sm" href="#" download aria-label="Download the video, 86 MB"><i class="ri-download-2-line"></i></a>
        </span>
    </figcaption>
    <details class="media-transcript">
        <summary>Transcript</summary>
        <ol>
            <li><button class="media-transcript-time" type="button" aria-label="Play from 0:00">0:00</button><span>Before the truck backs in, check the dock plate is down and the bay light is green.</span></li>
            <li aria-current="true"><button class="media-transcript-time" type="button" aria-label="Play from 0:18">0:18</button><span>Scan the delivery note first, not the pallet — the note is what the order is matched against.</span></li>
            <li><button class="media-transcript-time" type="button" aria-label="Play from 0:41">0:41</button><span>Count the cartons on the outside layer and compare with the quantity on the note.</span></li>
            <li><button class="media-transcript-time" type="button" aria-label="Play from 1:12">1:12</button><span>Anything crushed or wet gets a photo before the wrap comes off.</span></li>
            <li><button class="media-transcript-time" type="button" aria-label="Play from 1:40">1:40</button><span>Sign on the scanner, and the note is filed against the order on its own.</span></li>
        </ol>
    </details>
</figure>
<p class="form-hint" style="max-width:640px">
    The poster is a photograph by Ruchindra Gunasekara on Unsplash. The demo has no source: the
    app's <code>&lt;source&gt;</code> and <code>&lt;track kind="captions"&gt;</code> go inside the
    <code>&lt;video&gt;</code>.
</p>

Video tiles

A library of videos is a .file-grid with --wide, which gives each tile the room and a 16:9 thumbnail. On the thumbnail, .file-tile-play says it plays and .file-tile-badge in the corner is its length, both on a scrim that reads over any picture; the words “Length” are there for a screen reader. The rest is the file tile: the link that opens it, the meta line and the menu.

Photographs by Ruchindra Gunasekara, CHUTTERSNAP and Marcin Jozwiak on Unsplash.

<div style="max-width:820px">
    <ul class="file-grid file-grid--wide" aria-label="Training videos">
        <li class="file-tile">
            <a class="file-tile-open" href="#">
                <span class="file-tile-thumb">
                    <img src="https://images.unsplash.com/photo-1553413077-190dd305871c?w=480&amp;h=270&amp;fit=crop&amp;q=70&amp;auto=format"
                         width="480" height="270" loading="lazy" alt="" />
                    <i class="ri-play-fill file-tile-play" aria-hidden="true"></i>
                    <span class="file-tile-badge"><span class="visually-hidden">Length </span>4:32</span>
                </span>
                <span class="file-name">Receiving a pallet at dock 4</span>
            </a>
            <span class="file-meta"><time datetime="2026-09-12">12 Sep</time><span>Alex Fischer</span></span>
            <button class="btn btn-ghost btn-icon btn-sm file-tile-menu" type="button" aria-label="Actions for Receiving a pallet at dock 4"><i class="ri-more-2-line"></i></button>
        </li>
        <li class="file-tile">
            <a class="file-tile-open" href="#">
                <span class="file-tile-thumb">
                    <img src="https://images.unsplash.com/photo-1587293852726-70cdb56c2866?w=480&amp;h=270&amp;fit=crop&amp;q=70&amp;auto=format"
                         width="480" height="270" loading="lazy" alt="" />
                    <i class="ri-play-fill file-tile-play" aria-hidden="true"></i>
                    <span class="file-tile-badge"><span class="visually-hidden">Length </span>12:05</span>
                </span>
                <span class="file-name">Loading high racking safely</span>
            </a>
            <span class="file-meta"><time datetime="2026-09-03">3 Sep</time><span>Priya Nair</span></span>
            <button class="btn btn-ghost btn-icon btn-sm file-tile-menu" type="button" aria-label="Actions for Loading high racking safely"><i class="ri-more-2-line"></i></button>
        </li>
        <li class="file-tile">
            <a class="file-tile-open" href="#">
                <span class="file-tile-thumb">
                    <img src="https://images.unsplash.com/photo-1565891741441-64926e441838?w=480&amp;h=270&amp;fit=crop&amp;q=70&amp;auto=format"
                         width="480" height="270" loading="lazy" alt="" />
                    <i class="ri-play-fill file-tile-play" aria-hidden="true"></i>
                    <span class="file-tile-badge"><span class="visually-hidden">Length </span>1:48</span>
                </span>
                <span class="file-name">The end-of-shift handover</span>
            </a>
            <span class="file-meta"><time datetime="2026-08-28">28 Aug</time><span>Tomás Ferreira</span></span>
            <button class="btn btn-ghost btn-icon btn-sm file-tile-menu" type="button" aria-label="Actions for The end-of-shift handover"><i class="ri-more-2-line"></i></button>
        </li>
    </ul>
    <p class="form-hint sedna-mb-0">Photographs by Ruchindra Gunasekara, CHUTTERSNAP and Marcin Jozwiak on Unsplash.</p>
</div>