Skip to content

UI: Time Slider Component #267

@mihar-22

Description

@mihar-22

Seek slider connecting to the Media Store's time state. Extends base Slider component. Supports buffered progress indicator, and thumbnail previews.

Blocked by:

Usage

React

<TimeSlider.Root>
  <TimeSlider.Track>
    <TimeSlider.Buffered />
    <TimeSlider.Indicator />
    <TimeSlider.Thumb />
  </TimeSlider.Track>
</TimeSlider.Root>
<TimeSlider.Root>
  <TimeSlider.Track>
    <TimeSlider.Buffered />
    <TimeSlider.Indicator />
    <TimeSlider.Thumb />
  </TimeSlider.Track>
  <TimeSlider.Preview>
    <TimeSlider.Value />
  </TimeSlider.Preview>
</TimeSlider.Root>

HTML

<media-time-slider>
  <div class="track">
    <div class="buffered"></div>
    <div class="indicator"></div>
    <div class="thumb"></div>
  </div>
</media-time-slider>
<media-time-slider>
  <div class="track">
    <div class="buffered"></div>
    <div class="indicator"></div>
    <div class="thumb"></div>
  </div>
  <media-slider-preview>
    <media-time-slider-value></media-time-slider-value>
  </media-slider-preview>
</media-time-slider>

API

TimeSlider.Root

Extends Slider.Root (#275). Connects to time feature state. min is always 0, max is duration.

Extended Props

Prop Type Default Description
step number 1 Step increment in seconds (overrides Slider default)
keyStep number 5 Keyboard step in seconds (overrides Slider default)
seekWhileDragging boolean true Whether to seek during drag or only on release

Extended Callbacks

Callback Type Description
onSeekRequest (time: number) => void Fires before seek request is made
onSeek (time: number) => void Fires when seek completes

Extended State

Property Type Description
currentTime number Current playback time in seconds
duration number Total duration in seconds
buffered Array<[number, number]> Buffered time ranges
seeking boolean Whether media is currently seeking

Extended Data Attributes

Attribute Description
data-seeking Present when media is seeking
data-live Present for live streams

Extended CSS Variables

Variable Description
--slider-buffered Buffered percentage (0% to 100%)

TimeSlider.Buffered

Visualizes buffered progress. Width driven by --slider-buffered. Typically rendered behind the indicator.

TimeSlider.Value

Extends Slider.Value (#275). Displays formatted time.

Extended Props

Prop Type Default Description
showHours boolean | 'auto' 'auto' When to show hours. 'auto' shows if duration >= 1 hour
padHours boolean false Pad hours with leading zero
padMinutes boolean true Pad minutes with leading zero

Other Parts

TimeSlider.Track, TimeSlider.Indicator, TimeSlider.Thumb, TimeSlider.Preview — see Slider API (#275).

<media-time-slider> (HTML)

Extended Attributes

Attribute Type Default Description
step number 1 Step increment in seconds
key-step number 5 Keyboard step in seconds
seek-while-dragging boolean true Whether to seek during drag

<media-time-slider-value> (HTML)

Extended Attributes

Attribute Type Default Description
show-hours boolean | 'auto' 'auto' When to show hours
pad-hours boolean false Pad hours with leading zero
pad-minutes boolean true Pad minutes with leading zero

Tasks

Core (@videojs/core)

  • Implement TimeSliderCore extending SliderCore
  • Connect to time feature state
  • Integrate optimistic updates
  • Implement buffered range tracking

DOM (@videojs/core/dom)

  • Implement getTimeSliderRootProps(params) extending base slider props
  • Implement getTimeSliderBufferedProps(params) function
  • Implement getTimeSliderValueProps(params) function
  • Define TimeSliderDataAttributes interface
  • Define TimeSliderCssVars interface

React (@videojs/react)

  • Implement TimeSlider.Root component
  • Implement TimeSlider.Buffered component
  • Implement TimeSlider.Value component
  • Re-export Slider parts as TimeSlider parts

HTML (@videojs/html)

  • Implement TimeSliderElement extending SliderElement
  • Implement TimeSliderValueElement element

Testing

  • Core unit tests
  • Test time state connection
  • Test buffered indicator
  • Test time formatting
  • Add conformance test suite
  • Add React conformance test
  • Add HTML conformance test

Documentation

  • Create /docs/react/components/time-slider page
  • Create /docs/html/components/time-slider page

Design Notes

Buffered Indicator

Rendered behind the progress indicator to show buffered ranges:

.buffered {
  position: absolute;
  left: 0;
  width: var(--slider-buffered);
  background: rgba(255, 255, 255, 0.3);
}

.indicator {
  position: absolute;
  left: 0;
  width: var(--slider-fill);
  background: white;
}

Time Formatting

TimeSlider.Value formats seconds into H:MM:SS or M:SS:

function formatTime(seconds: number, options: FormatOptions): string {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = Math.floor(seconds % 60);
  
  const showHours = options.showHours === true || 
    (options.showHours === 'auto' && options.duration >= 3600);
  
  if (showHours) {
    const hStr = options.padHours ? String(h).padStart(2, '0') : String(h);
    return `${hStr}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
  }
  
  const mStr = options.padMinutes ? String(m).padStart(2, '0') : String(m);
  return `${mStr}:${String(s).padStart(2, '0')}`;
}

Seek While Dragging

When seekWhileDragging is true (default), the media seeks as the user drags. When false, seeking only occurs on release—useful for slower connections or live streams.

Optimistic Updates

Uses useOptimistic for responsive dragging. The slider shows pointer position immediately while seek requests are in flight. See #228 for details.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions