# media-time-slider-markers

Draws a marker on the time slider for each cue on the text tracks a filter matches, such as ad breaks

A part of the [time slider](https://videojs.org/docs/framework/html/reference/components/time-slider) that draws a marker for each cue on the text tracks a filter matches, such as ad breaks, quiz questions, or highlights. Its props, data attributes, and custom properties are listed with the time slider’s other parts.

## Import

```ts
import '@videojs/html/ui/time-slider-markers';
```

## Anatomy

```html
<media-time-slider>
  <media-slider-track>
    <media-slider-fill></media-slider-fill>
  </media-slider-track>
  <media-time-slider-markers label="ads"></media-time-slider-markers>
  <media-slider-thumb></media-slider-thumb>
</media-time-slider>
```

Each marker is a `<div>`, or a clone of a `<template>` child. The template must contain exactly one HTML root element, and stays in the light DOM.

```html
<media-time-slider-markers label="ads">
  <template>
    <div class="ad-marker"></div>
  </template>
</media-time-slider-markers>
```

## Behavior

The `kind`, `label`, and `language` attributes pick the tracks whose cues are drawn. The `filter` property takes a filter object, a function, or a [track definition](https://videojs.org/docs/framework/html/reference/api/define-text-track) instead, and takes priority over the attributes. With neither, nothing is drawn.

Tracks from the media and from the app are drawn alike. While the markers are rendered, the [text cues feature](https://videojs.org/docs/framework/html/reference/api/feature-text-cues) reads the tracks they match, so tracks it skips by default work too.

A cue whose end is its start is a point, drawn as a marker with no width and `data-point`. Any other cue is a range, spanning from its start to its end and clamped to the slider. Markers sit on the same span as the slider: from `0` to the media’s duration, or to the end of its seekable range while the duration is unknown. Cues outside that span, and every cue while it’s unknown, aren’t drawn. Markers are ordered by start, then end.

## Styling

| Attribute | Description |
| --- | --- |
| `data-active` | Present while the marker’s cue is active. |
| `data-point` | Present when the cue marks one moment rather than a span. |

Each marker also carries the slider’s data attributes, such as `data-orientation`, and its geometry through:

- `--media-slider-marker-start`
- `--media-slider-marker-end`
- `--media-slider-marker-width`, the marker’s size along the slider, `0%` for a point

Markers are unstyled. Position each one from its custom properties, and give points a visible width:

```css
media-time-slider-markers > div {
  position: absolute;
  inset-block: 0;
  left: var(--media-slider-marker-start);
  width: var(--media-slider-marker-width);
  min-width: 4px;
}

media-time-slider-markers > [data-active] {
  background: orange;
}
```

## Accessibility

The markers render with `aria-hidden="true"`; the slider’s value is what assistive technology reads. When a marker carries meaning a viewer needs, such as an upcoming ad break, convey it another way too.

## Examples

### Basic usage

An app track labeled `ads` holds a point at 8 seconds and a range from 18 to 24 seconds. A marker turns orange while its cue is active.

**index.html**

```html
<video-player class="html-time-slider-markers-basic">
  <media-container class="html-time-slider-markers-basic__container">
    <video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" autoplay muted playsinline loop></video>
    <media-time-slider class="html-time-slider-markers-basic__slider">
      <media-slider-track class="html-time-slider-markers-basic__track">
        <media-slider-fill class="html-time-slider-markers-basic__fill"></media-slider-fill>
      </media-slider-track>
      <media-time-slider-markers label="ads" class="html-time-slider-markers-basic__markers">
        <template>
          <div class="html-time-slider-markers-basic__marker"></div>
        </template>
      </media-time-slider-markers>
      <media-slider-thumb class="html-time-slider-markers-basic__thumb"></media-slider-thumb>
    </media-time-slider>
  </media-container>
</video-player>
```

**index.css**

```css
.html-time-slider-markers-basic__container {
  position: relative;
}

.html-time-slider-markers-basic__container video {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.html-time-slider-markers-basic__slider {
  position: absolute;
  right: 12px;
  bottom: 12px;
  left: 12px;
  display: flex;
  align-items: center;
  height: 20px;
  cursor: pointer;
}

.html-time-slider-markers-basic__track,
.html-time-slider-markers-basic__markers {
  position: absolute;
  right: 0;
  left: 0;
  height: 4px;
}

.html-time-slider-markers-basic__track {
  overflow: hidden;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 9999px;
}

.html-time-slider-markers-basic__fill {
  position: absolute;
  inset-block: 0;
  left: 0;
  width: var(--media-slider-fill);
  background: white;
}

.html-time-slider-markers-basic__marker {
  position: absolute;
  inset-block: 0;
  left: var(--media-slider-marker-start);
  width: var(--media-slider-marker-width);
  min-width: 4px;
  background: #facc15;
}

.html-time-slider-markers-basic__marker[data-point] {
  transform: translateX(-50%);
}

.html-time-slider-markers-basic__marker[data-active] {
  background: #f97316;
}

.html-time-slider-markers-basic__thumb {
  position: absolute;
  left: var(--media-slider-fill);
  width: 12px;
  height: 12px;
  background: white;
  border-radius: 50%;
  transform: translateX(-50%);
}
```

**index.ts**

```ts
import '@videojs/html/video/player';
import '@videojs/html/ui/container';
import '@videojs/html/ui/time-slider';
import '@videojs/html/ui/slider-track';
import '@videojs/html/ui/slider-fill';
import '@videojs/html/ui/slider-thumb';
import '@videojs/html/ui/time-slider-markers';

const player = document.querySelector('video-player');

player?.store.addTextTrack({
  kind: 'metadata',
  label: 'ads',
  cues: [{ startTime: 8 }, { startTime: 18, endTime: 24 }],
});
```

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
