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

PropTypeDefaultDetails
labelText | string | Text) | function''
negativeSignstring'-'
togglebooleanfalse
type'current' | 'duration' | 'remaining''current'

State

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

PropertyTypeDetails
type'current' | 'duration' | 'remaining'
secondsnumber
negativeboolean
textstring
phrasestring
datetimestring

Data attributes

AttributeTypeDetails
data-type'current' | 'duration' | 'remaining'

Group

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

Separator

Divider between time values. Hidden from screen readers.