2026-02-10 21:51:51 +00:00
|
|
|
/**
|
|
|
|
|
* PlayerBarProgress — Seek bar with 60fps (transform-based)
|
|
|
|
|
* KŌDŌ gradient: --chart-1 → --chart-2
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { useRef, useEffect } from 'react';
|
|
|
|
|
import { cn } from '@/lib/utils';
|
|
|
|
|
|
|
|
|
|
interface PlayerBarProgressProps {
|
|
|
|
|
currentTime: number;
|
|
|
|
|
duration: number;
|
|
|
|
|
onSeek: (pct: number) => void;
|
|
|
|
|
className?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function PlayerBarProgress({
|
|
|
|
|
currentTime,
|
|
|
|
|
duration,
|
|
|
|
|
onSeek,
|
|
|
|
|
className,
|
|
|
|
|
}: PlayerBarProgressProps) {
|
|
|
|
|
const barRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const pct = duration > 0 ? Math.max(0, Math.min(1, currentTime / duration)) : 0;
|
|
|
|
|
|
|
|
|
|
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
|
|
|
if (!barRef.current) return;
|
|
|
|
|
const rect = barRef.current.getBoundingClientRect();
|
|
|
|
|
const x = e.clientX - rect.left;
|
|
|
|
|
onSeek(Math.max(0, Math.min(1, x / rect.width)));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
ref={barRef}
|
|
|
|
|
role="slider"
|
|
|
|
|
aria-label="Progression"
|
|
|
|
|
aria-valuemin={0}
|
|
|
|
|
aria-valuemax={duration}
|
|
|
|
|
aria-valuenow={currentTime}
|
|
|
|
|
tabIndex={0}
|
|
|
|
|
className={cn(
|
|
|
|
|
'absolute bottom-0 left-0 right-0 h-1.5 z-20 cursor-pointer',
|
refactor: Phase 5 — Migrate layout shell to SUMI tokens
- Sidebar: bg-raised, border-faint tokens
- Header: glass bg + backdrop-blur-12px, z-200 sticky, SUMI durations
- PlayerBarGlass: glass-bg + blur-16px, accent colors, remove glow
- PlayerBarProgress: solid accent fill, SUMI border tokens
- PlayerBarRight/TrackInfo: text-foreground, SUMI border tokens
- MiniPlayer: glass-bg, border-faint, z-200, SUMI shadows
- GlobalPlayer: SUMI z-index and duration tokens
- DashboardLayout: SUMI z-raised, duration tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 01:01:39 +00:00
|
|
|
'bg-[var(--sumi-border-default)] hover:bg-[var(--sumi-border-strong)] transition-colors duration-[var(--sumi-duration-fast)]',
|
2026-02-10 21:51:51 +00:00
|
|
|
className,
|
|
|
|
|
)}
|
|
|
|
|
onClick={handleClick}
|
|
|
|
|
>
|
|
|
|
|
<div
|
refactor: Phase 5 — Migrate layout shell to SUMI tokens
- Sidebar: bg-raised, border-faint tokens
- Header: glass bg + backdrop-blur-12px, z-200 sticky, SUMI durations
- PlayerBarGlass: glass-bg + blur-16px, accent colors, remove glow
- PlayerBarProgress: solid accent fill, SUMI border tokens
- PlayerBarRight/TrackInfo: text-foreground, SUMI border tokens
- MiniPlayer: glass-bg, border-faint, z-200, SUMI shadows
- GlobalPlayer: SUMI z-index and duration tokens
- DashboardLayout: SUMI z-raised, duration tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 01:01:39 +00:00
|
|
|
className="h-full rounded-r bg-[var(--sumi-accent)] transition-[transform] duration-75 ease-out will-change-transform"
|
2026-02-10 21:51:51 +00:00
|
|
|
style={{ transform: `scaleX(${pct})`, transformOrigin: 'left' }}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|