Limeplay - Open Source Video Player UI ComponentsLimeplay

Timeline Labels

Timeline Labels provide semantic time display components for media players. These components automatically format time based on duration and provide proper accessibility attributes.

Installation

Install the component

npx shadcn add @limeplay/timeline-labels

Add Event & Action Bridge

Import the useTimelineStates hook in your existing PlayerHooks component.

components/limeplay/player-hooks.tsx
import React from "react"

import { useShakaPlayer } from "@/hooks/limeplay/use-shaka-player"
import { useTimelineStates } from "@/hooks/limeplay/use-timeline"

export const PlayerHooks = React.memo(() => {
  useShakaPlayer()
  useTimelineStates() 

  return null
})

Add the Store States

lib/create-media-store.ts
import { createPlayerStore, PlayerStore } from "@/hooks/limeplay/use-player"
import {
  createTimelineStore,
  TimelineStore,
} from "@/hooks/limeplay/use-timeline"


export type TypeMediaStore = PlayerStore & TimelineStore & {} 

export function createMediaStore(initProps?: Partial<CreateMediaStoreProps>) {
  const mediaStore = create<TypeMediaStore>()((...etc) => ({
    ...createPlayerStore(...etc),
    ...createTimelineStore(...etc),
    ...initProps,
  }))
  return mediaStore
}

Example Usage

  1. Compose the labels
components/player/timeline-control.tsx
"use client"

import { useState } from "react"

import { Button } from "@/components/ui/button"
import { useMediaStore } from "@/components/limeplay/media-provider"
import {
  Duration,
  Elapsed,
  HoverTime,
  LiveLatency,
  Remaining,
} from "@/components/limeplay/timeline-labels"

export function TimelineSliderControl() {
  const [showRemaining, setShowRemaining] = useState(false)
  const isLive = useMediaStore((state) => state.isLive)

  return (
    <div className="my-auto flex grow items-center gap-3 select-none">
      {!isLive && <Elapsed className="text-xs font-medium" />}
      {!isLive && (
        <Button
          variant="ghost"
          size="sm"
          onClick={() => {
            setShowRemaining(!showRemaining)
          }}
          aria-label={
            showRemaining ? "Show total duration" : "Show remaining time"
          }
          aria-pressed={showRemaining}
        >
          {showRemaining ? (
            <Remaining className="text-xs font-medium" />
          ) : (
            <Duration className="text-xs font-medium" />
          )}
        </Button>
      )}
    </div>
  )
}

Understanding

Timeline Labels components use the useTimeline() hook to access timeline state from the media store.

All components automatically:

  • Format time based on duration (HH:MM:SS or MM:SS)
  • Include proper dateTime attributes for semantic HTML
  • Provide screen reader support with role="timer" and hidden labels
  • Use tabular-nums for consistent number width

Accessibility Features

  • Semantic HTML: Uses <time> element with proper dateTime attribute
  • Screen Reader Labels: Hidden labels announce "Elapsed", "Remaining", "Duration", etc.
  • ARIA Roles: role="timer" for live-updating time displays
  • Visual Clarity: tabular-nums ensures numbers don't shift during playback

Components

All timeline label components extend React.HTMLProps<HTMLTimeElement>, allowing you to pass standard HTML time element props like className, style, etc.

Elapsed

Current playback time.

Remaining

Time remaining (negative prefix).

Duration

Total media duration.

HoverTime

Time at cursor position on timeline.

LiveLatency

Latency for live streams (null for VOD).

On this page