HoverCard component (new): - Rich preview cards on hover with framer-motion animation - Viewport-aware positioning, portal rendering, open/close delays - UserHoverContent: Discord-style user preview (avatar, bio, stats, follow) - TrackHoverContent: Spotify-style track preview (cover, stats, play) Audio player — Spotify-like 3-column layout: - grid-cols-3 layout: track info | controls | volume+queue - Progress bar moved to top edge (minimal variant) - Glassmorphism (bg-background/95 backdrop-blur-md) - Prominent centered play button (h-10 w-10 rounded-full, active:scale-95) - Title marquee animation for long track names - Reduced padding for tighter premium feel Scrollbar styling: - Migrated hardcoded rgba() to semantic tokens via color-mix(in oklch) - Added transition on thumb hover for smooth visual feedback ContextMenu integration: - TrackListRow wrapped with ContextMenu (play, like, more actions) - Dynamic items based on available callbacks Co-authored-by: Cursor <cursoragent@cursor.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import { cn } from '@/lib/utils';
|
|
import { Skeleton } from '@/components/ui/skeleton';
|
|
|
|
interface AudioPlayerSkeletonProps {
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* Skeleton pour l'état Loading du lecteur (barre fixe en bas).
|
|
*/
|
|
export function AudioPlayerSkeleton({ className }: AudioPlayerSkeletonProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'fixed bottom-0 left-0 right-0 bg-background/95 backdrop-blur-md border-t border-border z-50',
|
|
className,
|
|
)}
|
|
>
|
|
{/* Top progress bar skeleton */}
|
|
<Skeleton className="w-full h-1 rounded-none" />
|
|
<div className="container mx-auto px-4 py-2">
|
|
<div className="grid grid-cols-3 items-center gap-4">
|
|
{/* Left: Track info */}
|
|
<div className="flex items-center gap-3 min-w-0">
|
|
<Skeleton className="w-10 h-10 rounded shrink-0" />
|
|
<div className="flex-1 space-y-2 min-w-0">
|
|
<Skeleton className="h-3 w-3/4 rounded" />
|
|
<Skeleton className="h-2 w-1/2 rounded" />
|
|
</div>
|
|
</div>
|
|
{/* Center: Controls */}
|
|
<div className="flex items-center justify-center gap-1">
|
|
{[1, 2].map((i) => (
|
|
<Skeleton key={i} className="h-9 w-9 rounded" />
|
|
))}
|
|
<Skeleton className="h-10 w-10 rounded-full" />
|
|
{[4, 5].map((i) => (
|
|
<Skeleton key={i} className="h-9 w-9 rounded" />
|
|
))}
|
|
</div>
|
|
{/* Right: Volume + Queue */}
|
|
<div className="flex items-center justify-end gap-2">
|
|
<Skeleton className="h-9 w-9 rounded" />
|
|
<Skeleton className="w-24 h-2 rounded" />
|
|
<Skeleton className="h-9 w-9 rounded" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|