Skip to content
FrameworkStyle

Time

Time display components for showing current time, duration, and remaining time in a video player

Anatomy

<Time.Group>
  <Time.Value type="current" />
  <Time.Separator />
  <Time.Value type="duration" />
</Time.Group>

Behavior

Three display types — current, duration, and remaining — in digital format with smart padding:

  • Hours are never padded (1:05:30, not 01:05:30)
  • Minutes are padded when hours are shown (1:05:30, but 5:30)
  • Seconds are always padded (1:05, not 1:5)

Hour display is triggered when either the current value or the duration exceeds 1 hour, ensuring consistency within a Group. Remaining time displays a negative sign (customizable via the negativeSign prop).

Use toggle to let current displays switch between elapsed and remaining time, or remaining and duration displays switch between those two values. The initial display comes from type.

<Time.Value toggle />
<Time.Value toggle type="remaining" />
<Time.Value toggle type="duration" />

Styling

The negative sign is rendered inside <span aria-hidden="true"> and can be hidden with CSS:

[data-type="remaining"] > span[aria-hidden] {
  display: none;
}

Accessibility

Each <Time.Value> has:

  • aria-label for the static role label (“Current time”, “Duration”, “Remaining”)
  • aria-valuetext for the dynamic human-readable time (“1 minute, 30 seconds”)

No aria-live region is used — time updates too frequently and might overwhelm screen readers. The separator is aria-hidden="true" since screen readers already hear each time value separately. The negative sign is also aria-hidden because aria-valuetext already conveys “remaining”. In React, <time datetime> provides machine-readable time for parsers.

Toggleable time displays receive role="button" and keyboard support for Enter and Space.

Examples

Current Time

import { createPlayer, Time } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function CurrentTime() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <Time.Value type="current" className="media-time" />
      </Player.Container>
    </Player.Provider>
  );
}

Current / Duration

import { createPlayer, Time } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function CurrentDuration() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <Time.Group className="time-group">
          <Time.Value type="current" />
          <Time.Separator />
          <Time.Value type="duration" />
        </Time.Group>
      </Player.Container>
    </Player.Provider>
  );
}

Remaining

import { createPlayer, Time } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function Remaining() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <Time.Value type="remaining" className="media-time" />
      </Player.Container>
    </Player.Provider>
  );
}

Custom Separator

import { createPlayer, Time } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function CustomSeparator() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <Time.Group className="time-group">
          <Time.Value type="current" />
          <Time.Separator> of </Time.Separator>
          <Time.Value type="duration" />
        </Time.Group>
      </Player.Container>
    </Player.Provider>
  );
}

Custom Negative Sign

import { createPlayer, Time } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const Player = createPlayer({ features: videoFeatures });

export default function CustomNegativeSign() {
  return (
    <Player.Provider>
      <Player.Container className="media-container">
        <Video
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <Time.Value type="remaining" negativeSign="~" className="media-time" />
      </Player.Container>
    </Player.Provider>
  );
}

API Reference

Value

Displays a formatted time value (current, duration, or remaining).

Props

Prop Type Default Details
label string | function ''
negativeSign string '-'
toggle boolean false
type 'current' | 'duration' | 'remaining' 'current'

State

State is accessible via the render, className, and style props.

Property Type Details
type 'current' | 'duration' | 'remaining'
seconds number
negative boolean
text string
phrase string
datetime string

Data attributes

Attribute Type Details
data-type 'current' | 'duration' | 'remaining'

Group

Container for composed time displays. Renders a <span> element.

Separator

Divider between time values. Hidden from screen readers.