PURPOSE
Stateless controlled-input component for the Weapon Workbench timeline. Renders a horizontal range slider plus a readout label and an “auto” resume button, letting the user scrub a normalized timeline parameter t in [0, 1] or hand control back to automatic playback.
OWNS
- Pure presentational JSX: a flex container, a
<input type="range">, a monospace readout<span>, and a conditional▶ auto<button>. - Local derived state only:
isAuto(whether the incomingcurrentTequals the string'auto') anddisplayT(the numeric value to show —0when auto). - Inline styling for the container, slider, readout, and button.
- Test ids
timeline-scrubber,timeline-slider, andtimeline-auto-resume.
READS FROM
Props.currentT— either a number in[0, 1]or the literal string'auto', supplied by the parent screen.- The native range
<input>changeevent value (e.target.value), parsed viaparseFloat.
PUSHES TO
Props.onScrub(t: number)— invoked on every slideronChangewith the parsed float.Props.onAutoResume()— invoked when the user releases the slider (onMouseUp) while not already in auto mode, and when the explicit▶ autobutton is clicked.
DOES NOT
- Hold any internal React state (no
useState,useRef,useEffect). - Persist values to a store, localStorage, or telemetry sink.
- Manage playback, timers, or animation — the parent owns the auto-advance loop.
- Validate or clamp
currentT; assumes the parent stays in the documented domain. - Render touch-specific handlers (
onTouchEnd); onlyonMouseUptriggers auto-resume on release. - Apply styles from any stylesheet — all styling is inline.
Signals
- Outbound scrub:
onScrub(parseFloat(value))on sliderchange. - Outbound auto-resume:
onAutoResume()on slidermouseUp(only when not currently auto) and on▶ autobutton click. - Visual signal: readout shows
'auto'when in auto mode, otherwise"{t.toFixed(2)} / 1.00"; the▶ autobutton is mounted only when not in auto mode.
Entry points
- Named export
TimelineScrubber(props: Props). Propsinterface:currentT: number | 'auto',onScrub: (t: number) => void,onAutoResume: () => void.
Pattern notes
- Discriminated value pattern: a single prop (
currentT) encodes both the auto-mode flag and the numeric scrub position via anumber | 'auto'union, so the parent never has to send a separate boolean. - Fully controlled input:
value={displayT}plusonChange={onScrub}means the slider reflects parent state immediately; there is no local debouncing. - Range bounds (
min=0,max=1,step=0.01) are hard-coded — the timeline parameter is always normalized. - Auto-resume on
onMouseUponly fires outside auto mode, preventing redundant callbacks when the user merely clicks the slider while auto playback is already active. - Inline styling and inline color literals (
#1a1a26,#44ffcc,#aaa) — no theme token usage. - Accessibility:
aria-label="timeline"on the slider; no label on the auto button beyond its text content.