Skip to content

Track Timeline

Arrange segments on tracks along a time ruler, and move, trim and snap them by pointer or keyboard, such as video clips.

import { TimelineClip, TimelineTrack, TrackTimeline } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use a track timeline for an edit made of parts on tracks: a podcast cut, a song sketch, a video's voice-over, a meeting's highlights. Each track is a lane in its chart color with its name, mute and solo keys and a level strip; each clip is a rounded bar holding the slice of the track's sound it plays, drawn from loudness samples you pass (it decodes no audio) and scaled by its gain. Drag a clip to move it, or its edges to trim it. Both snap to the other clips' edges and to the playhead, and a guide shows the edge they caught. A ruler of mono timecodes runs along the top, with the playhead on it. For a single recording's seek bar, use a Waveform Scrubber.

import { TrackTimeline } from '@youj/react'

<TrackTimeline
  tracks={[
    { id: 'host', name: 'Host', caption: 'Mic 1', peaks: hostPeaks },
    { id: 'music', name: 'Music bed', peaks: musicPeaks, muted: true },
  ]}
  clips={clips}
  onClipsChange={setClips}
  onTrackChange={(id, change) => updateTrack(id, change)}
  duration={30}
  position={time}
  onPositionChange={setTime}
  value={selected}
  onValueChange={setSelected}
/>

clips is controlled: every move and trim reports the whole list through onClipsChange. A clip sits from start to end on its track, plays its track's source from offset, and scales its wave by gain in decibels. A track's peaks are its whole source as loudness from 0 to 1, one sample every resolution seconds (0.1). A clip never moves into its neighbor on the same track, never trims past its source, and stays at least half a second long. formatClipTime(seconds, locale) formats times the way the timeline speaks them (0:12.5).

Reference

Propstracks, clips, duration… (21)

Props

TrackTimeline props
PropType
tracksRequiredreadonly TimelineTrack[]–
clipsRequiredreadonly TimelineClip[]

The clips (controlled): every move and trim reports the whole list.

–
onClipsChange(clips: TimelineClip[]) => void–
onTrackChange(id: string, change: { muted?: boolean; solo?: boolean }) => void–
durationRequirednumber

The timeline's length, in seconds.

–
positionnumber

The playhead, in seconds (controlled).

–
defaultPositionnumber

default 0

0
onPositionChange(seconds: number) => void–
valuestring | null

The selected clip's id (controlled); null for none.

–
defaultValuestring | null

default null

null
onValueChange(id: string | null) => void–
zoomnumber

Pixels per second (controlled). Default: the whole timeline in view, at least 8.

–
defaultZoomnumber–
onZoomChange(pxPerSecond: number) => void–
resolutionnumber

Seconds per sample in the tracks' peaks.

default 0.1

0.1
snapboolean

Snap moves and trims to the other clips' edges and the playhead.

default true

true
stepnumber

Seconds an arrow key moves or trims a clip.

default 0.5

0.5
playingboolean

While playing, the meters read the tracks at the playhead and the lane follows it.

default false

false
labelstring

The timeline's accessible name. Default: the labels' "Timeline".

–
localestring

Default: the YoujProvider locale.

–
soundboolean

With sound on, catching a snap point plays tick.

default true

true
Other props pass through: extends ComponentProps<'div'>.
StylingParts and data attributes

Styling

Parts: track-timeline (with data-dragging), track-timeline-heads, track-timeline-zoom, track-timeline-track-head (with data-muted and data-solo), track-timeline-track-name, track-timeline-track-caption, track-timeline-mute, track-timeline-solo, track-timeline-meter, track-timeline-lane, track-timeline-ruler, track-timeline-ruler-control, track-timeline-ruler-track, track-timeline-time, track-timeline-playhead, track-timeline-tracks, track-timeline-track, track-timeline-clip (with data-selected and data-muted), track-timeline-clip-name, track-timeline-wave, track-timeline-handle (with data-edge), track-timeline-playhead-line and track-timeline-snap. In Bezel the track captions are mono capital eyebrows and the timecodes and clip names are mono. On a narrow timeline the heads keep the name, the keys and the level strip.

MotionPlaying, drag and trim, handles · reduced motion

Motion

Motion tokens
MomentTokens
Playingeach level strip eases between readings as the playhead passes through the track’s clips
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)
Drag and trimthe clip and its edges follow the pointer, never eased; a snap shows its guide at once
no token

Handlesa trim handle thickens on hover
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)

Reduced motion

The level strips jump to each reading; everything else was never eased.

Reduced motion

The level strips jump to each reading instead of easing. Dragging, trimming and the playhead are unchanged, since they never animate.

AccessibilityKeyboard, ARIA, focus

Accessibility

  • The timeline is a group named by label (default "Timeline"), and each track a group named by the track. Every clip is a button and a tab stop, named by its name, range and track ("answer, 0:06.5 to 0:12.5, Guest") and described by a hint that explains the keys.
  • Focusing a clip selects it (aria-pressed). Arrow keys move it by step (half a second), Shift ten times as far, stopping at the first snap point on the way; the new range is announced. Escape lets go of it.
  • The selected clip's edges come next in the tab order, as sliders named "Start of answer" and "End of answer" that trim it from the keyboard.
  • The playhead is a slider on the ruler, spoken as the time and the length ("0:09.0 of 0:30.0"). Mute and solo are toggle buttons named with their track ("Mute Guest").
  • Time runs left to right in every script, like a tape, so the lane keeps its direction under RTL, the arrow keys included; the heads and their text follow the page.
  • With sound on, catching a snap point while dragging plays tick.
  • Its words come from the labels (trackTimeline, trackTimelineHint, trackTimelineClip, trackTimelineRange, trackTimelineClipStart, trackTimelineClipEnd, trackTimelineMute, trackTimelineSolo, trackTimelinePlayhead, zoomIn, zoomOut), translated by the language packs.