@@ -4,6 +4,7 @@ import { useMemo } from 'react';
44import { RotateCcwIcon } from 'lucide-react' ;
55import { Switch } from '@/components/ui/switch' ;
66import { SidebarPanel } from './SidebarPanel' ;
7+ import type { VelocityColorPreset } from '../lib/trajectory-types' ;
78
89const BODY_TRACK_LAYOUT = [
910 {
@@ -70,6 +71,7 @@ interface OverlaySettingsPanelProps {
7071 onHideAllTracks : ( ) => void ;
7172 onToggleTrajectoryTrack : ( trackName : string ) => void ;
7273 onRemoveMetadata ?: ( ) => void ;
74+ velocityColorPreset ?: VelocityColorPreset | null ;
7375}
7476
7577export function OverlaySettingsPanel ( {
@@ -88,6 +90,7 @@ export function OverlaySettingsPanel({
8890 onHideAllTracks,
8991 onToggleTrajectoryTrack,
9092 onRemoveMetadata,
93+ velocityColorPreset,
9194} : OverlaySettingsPanelProps ) {
9295 const visibleTrackNameSet = useMemo ( ( ) => new Set ( visibleTrajectoryTrackNames ) , [ visibleTrajectoryTrackNames ] ) ;
9396 const availableTrackNameSet = useMemo ( ( ) => new Set ( availableTrajectoryTrackNames ) , [ availableTrajectoryTrackNames ] ) ;
@@ -159,6 +162,29 @@ export function OverlaySettingsPanel({
159162 </ div >
160163 </ div >
161164
165+ { showTrajectory && velocityColorPreset && (
166+ < div >
167+ < p className = "mb-2 text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500" >
168+ Legend
169+ </ p >
170+ < div className = "grid grid-cols-3 gap-2 rounded-lg border border-gray-100 px-4 py-3 dark:border-gray-700 dark:bg-gray-800/60" >
171+ { ( [
172+ { label : 'Slower Velocity' , bgr : velocityColorPreset . slowBgr } ,
173+ { label : 'Average Velocity' , bgr : velocityColorPreset . midBgr } ,
174+ { label : 'Faster Velocity' , bgr : velocityColorPreset . fastBgr } ,
175+ ] as const ) . map ( ( { label, bgr } ) => (
176+ < div key = { label } className = "flex items-center gap-2" >
177+ < div
178+ className = "h-4 w-4 shrink-0 rounded-sm border border-black/10 dark:border-white/10"
179+ style = { { backgroundColor : `rgb(${ bgr [ 2 ] } , ${ bgr [ 1 ] } , ${ bgr [ 0 ] } )` } }
180+ />
181+ < span className = "text-[11px] font-medium leading-tight text-gray-600 dark:text-gray-400" > { label } </ span >
182+ </ div >
183+ ) ) }
184+ </ div >
185+ </ div >
186+ ) }
187+
162188 { showTrajectory && (
163189 < div >
164190 < div className = "mb-2 flex items-center justify-between" >
@@ -176,9 +202,9 @@ export function OverlaySettingsPanel({
176202 step = { 0.1 }
177203 value = { trajectoryHistorySeconds }
178204 onChange = { ( event ) => onSetTrajectoryHistorySeconds ( parseFloat ( event . target . value ) ) }
179- className = "h-3 w-full cursor-pointer appearance-none rounded-lg bg-gray-300 accent-cyan -600 hover:accent-cyan -700 dark:bg-gray-700"
205+ className = "h-3 w-full cursor-pointer appearance-none rounded-lg bg-gray-300 accent-amber -600 hover:accent-amber -700 dark:bg-gray-700"
180206 />
181- < div className = "mt-2 flex items-center justify-between text-[11px] font-medium text-cyan -700 dark:text-cyan -300" >
207+ < div className = "mt-2 flex items-center justify-between text-[11px] font-medium text-amber -700 dark:text-amber -300" >
182208 < span > 0.0s keeps the full history visible</ span >
183209 < span > Limit trail length client-side</ span >
184210 </ div >
@@ -197,7 +223,7 @@ export function OverlaySettingsPanel({
197223 < button
198224 type = "button"
199225 onClick = { allTracksVisible ? onHideAllTracks : onShowAllTracks }
200- className = "rounded-full border border-cyan -200 bg-cyan -50 px-3 py-1.5 text-[11px] font-semibold text-cyan -700 transition-colors hover:bg-cyan -100 dark:border-cyan -900 dark:bg-cyan -950/50 dark:text-cyan -300"
226+ className = "rounded-full border border-amber -200 bg-amber -50 px-3 py-1.5 text-[11px] font-semibold text-amber -700 transition-colors hover:bg-amber -100 dark:border-amber -900 dark:bg-amber -950/50 dark:text-amber -300"
201227 >
202228 { allTracksVisible ? 'Hide All' : 'Show All' }
203229 </ button >
@@ -206,12 +232,12 @@ export function OverlaySettingsPanel({
206232
207233 { availableTrajectoryTrackNames . length > 0 ? (
208234 < fieldset className = "space-y-4" >
209- < div className = "relative h-88 w-full overflow-hidden rounded-2xl border border-cyan -100 bg-gradient-to-b from-cyan -50 to-white px-4 py-5 dark:border-cyan -950/60 dark:from-cyan -950/20 dark:to-gray-900" >
210- < div className = "pointer-events-none absolute left-1/2 top-[16%] h-[44%] w-px -translate-x-1/2 bg-cyan -200 dark:bg-cyan -900" />
211- < div className = "pointer-events-none absolute left-1/2 top-[26%] h-px w-[46%] -translate-x-1/2 bg-cyan -200 dark:bg-cyan -900" />
212- < div className = "pointer-events-none absolute left-1/2 top-[60%] h-px w-[22%] -translate-x-1/2 bg-cyan -200 dark:bg-cyan -900" />
213- < div className = "pointer-events-none absolute left-[40%] top-[60%] h-[24%] w-px bg-cyan -200 dark:bg-cyan -900" />
214- < div className = "pointer-events-none absolute left-[60%] top-[60%] h-[24%] w-px bg-cyan -200 dark:bg-cyan -900" />
235+ < div className = "relative h-88 w-full overflow-hidden rounded-2xl border border-amber -100 bg-gradient-to-b from-amber -50 to-white px-4 py-5 dark:border-amber -950/60 dark:from-amber -950/20 dark:to-gray-900" >
236+ < div className = "pointer-events-none absolute left-1/2 top-[16%] h-[44%] w-px -translate-x-1/2 bg-amber -200 dark:bg-amber -900" />
237+ < div className = "pointer-events-none absolute left-1/2 top-[26%] h-px w-[46%] -translate-x-1/2 bg-amber -200 dark:bg-amber -900" />
238+ < div className = "pointer-events-none absolute left-1/2 top-[60%] h-px w-[22%] -translate-x-1/2 bg-amber -200 dark:bg-amber -900" />
239+ < div className = "pointer-events-none absolute left-[40%] top-[60%] h-[24%] w-px bg-amber -200 dark:bg-amber -900" />
240+ < div className = "pointer-events-none absolute left-[60%] top-[60%] h-[24%] w-px bg-amber -200 dark:bg-amber -900" />
215241
216242 { BODY_TRACK_LAYOUT . map ( ( track ) => {
217243 const isAvailable = availableTrackNameSet . has ( track . trackName ) ;
@@ -230,8 +256,8 @@ export function OverlaySettingsPanel({
230256 disabled = { ! isAvailable }
231257 className = { `absolute min-w-26 rounded-full border px-3 py-2 text-center text-xs font-semibold shadow-sm transition-all ${ track . className } ${ isAvailable
232258 ? isVisible
233- ? 'border-cyan -500 bg-cyan -500 text-white shadow-cyan -200 dark:border-cyan -400 dark:bg-cyan -400 dark:text-cyan -950 dark:shadow-transparent'
234- : 'border-gray-200 bg-white text-gray-500 hover:border-cyan -300 hover:text-cyan -700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:border-cyan -700 dark:hover:text-cyan -300'
259+ ? 'border-amber -500 bg-amber -500 text-white shadow-amber -200 dark:border-amber -400 dark:bg-amber -400 dark:text-amber -950 dark:shadow-transparent'
260+ : 'border-gray-200 bg-white text-gray-500 hover:border-amber -300 hover:text-amber -700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:border-amber -700 dark:hover:text-amber -300'
235261 : 'cursor-not-allowed border-dashed border-gray-200 bg-gray-100 text-gray-400 shadow-none dark:border-gray-700 dark:bg-gray-800/70 dark:text-gray-500'
236262 } `}
237263 >
0 commit comments