style(TrackListRow): elevate visual fidelity to premium standards
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6a8ef31582
commit
aeec29caa1
2 changed files with 43 additions and 21 deletions
|
|
@ -24,7 +24,15 @@ const mockTrack = {
|
|||
const meta = {
|
||||
title: 'Components/Features/Tracks/TrackListRow',
|
||||
component: TrackListRow,
|
||||
parameters: { layout: 'centered' },
|
||||
tags: ['autodocs'],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="w-full max-w-2xl p-4 bg-background border border-border rounded-[var(--radius-xl)] min-h-layout-story">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
onTrackClick: { action: 'track clicked' },
|
||||
onTrackPlay: { action: 'play clicked' },
|
||||
|
|
@ -72,3 +80,16 @@ export const Liked: Story = {
|
|||
isLiked: true,
|
||||
},
|
||||
};
|
||||
|
||||
/** List + selection + metadata to validate tokens. */
|
||||
export const VisualStressTest: Story = {
|
||||
args: {
|
||||
track: mockTrack,
|
||||
format: 'list',
|
||||
showMetadata: true,
|
||||
showCover: true,
|
||||
showDuration: true,
|
||||
showSelection: true,
|
||||
isSelected: true,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ export function TrackListRow({
|
|||
<tr
|
||||
role="row"
|
||||
className={cn(
|
||||
'hover:bg-muted/50 transition-colors',
|
||||
isSelected && 'bg-kodo-cyan/10 dark:bg-kodo-cyan/20',
|
||||
'hover:bg-muted/50 transition-colors duration-[var(--duration-normal)]',
|
||||
isSelected && 'bg-primary/10',
|
||||
className,
|
||||
)}
|
||||
onClick={() => onTrackClick?.(track)}
|
||||
|
|
@ -92,12 +92,12 @@ export function TrackListRow({
|
|||
<img
|
||||
src={track.cover}
|
||||
alt={`Cover de ${track.title}`}
|
||||
className="w-full h-full object-cover rounded"
|
||||
className="w-full h-full object-cover rounded-[var(--radius-md)]"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-muted flex items-center justify-center rounded">
|
||||
<div className="w-full h-full bg-muted flex items-center justify-center rounded-[var(--radius-md)]">
|
||||
<svg
|
||||
className="w-4 h-4 text-muted-foreground"
|
||||
className="w-4 h-4 text-muted-foreground/90"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
|
|
@ -112,7 +112,7 @@ export function TrackListRow({
|
|||
</div>
|
||||
)}
|
||||
{showActions && (
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 bg-black/40 transition-opacity rounded">
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 bg-black/40 transition-opacity duration-[var(--duration-normal)] rounded-[var(--radius-md)]">
|
||||
<button
|
||||
onClick={handlePlay}
|
||||
aria-label={isPlaying ? 'Mettre en pause' : 'Lire'}
|
||||
|
|
@ -124,15 +124,15 @@ export function TrackListRow({
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
<span>{track.title}</span>
|
||||
<span className="tracking-tight">{track.title}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="p-2">{track.artist}</td>
|
||||
<td className="p-2 text-muted-foreground/90 tracking-tight">{track.artist}</td>
|
||||
{showMetadata && (
|
||||
<td className="p-2 text-muted-foreground">{track.album}</td>
|
||||
<td className="p-2 text-muted-foreground/90 tracking-tight">{track.album}</td>
|
||||
)}
|
||||
{showDuration && (
|
||||
<td className="p-2 text-right text-muted-foreground text-xs">
|
||||
<td className="p-2 text-right text-muted-foreground/90 text-xs tabular-nums tracking-tight">
|
||||
{Math.floor(track.duration / 60)}:
|
||||
{String(track.duration % 60).padStart(2, '0')}
|
||||
</td>
|
||||
|
|
@ -145,8 +145,9 @@ export function TrackListRow({
|
|||
<li
|
||||
role="listitem"
|
||||
className={cn(
|
||||
'flex items-center gap-4 p-2 rounded-md hover:bg-muted/50 group h-14 transition-colors',
|
||||
isSelected && 'bg-kodo-cyan/10 dark:bg-kodo-cyan/20',
|
||||
'flex items-center gap-4 p-2 rounded-[var(--radius-md)] hover:bg-muted/50 group h-14',
|
||||
'transition-colors duration-[var(--duration-normal)]',
|
||||
isSelected && 'bg-primary/10',
|
||||
className,
|
||||
)}
|
||||
onClick={() => onTrackClick?.(track)}
|
||||
|
|
@ -169,12 +170,12 @@ export function TrackListRow({
|
|||
<img
|
||||
src={track.cover}
|
||||
alt={`Cover de ${track.title}`}
|
||||
className="w-full h-full object-cover rounded"
|
||||
className="w-full h-full object-cover rounded-[var(--radius-md)]"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-muted flex items-center justify-center rounded">
|
||||
<div className="w-full h-full bg-muted flex items-center justify-center rounded-[var(--radius-md)]">
|
||||
<svg
|
||||
className="w-5 h-5 text-muted-foreground"
|
||||
className="w-5 h-5 text-muted-foreground/90"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
|
|
@ -192,7 +193,7 @@ export function TrackListRow({
|
|||
)}
|
||||
|
||||
{showActions && (
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 bg-black/40 transition-opacity rounded">
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 bg-black/40 transition-opacity duration-[var(--duration-normal)] rounded-[var(--radius-md)]">
|
||||
<button
|
||||
aria-label={isPlaying ? 'Mettre en pause' : 'Lire'}
|
||||
onClick={handlePlay}
|
||||
|
|
@ -205,16 +206,16 @@ export function TrackListRow({
|
|||
</div>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-medium truncate">{track.title}</div>
|
||||
<div className="font-medium truncate tracking-tight">{track.title}</div>
|
||||
{showMetadata && (
|
||||
<div className="text-xs text-muted-foreground truncate">
|
||||
<div className="text-xs text-muted-foreground/90 truncate tracking-tight">
|
||||
{track.artist} {track.album && `• ${track.album}`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{showDuration && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<div className="text-xs text-muted-foreground/90 tabular-nums tracking-tight">
|
||||
{Math.floor(track.duration / 60)}:
|
||||
{String(track.duration % 60).padStart(2, '0')}
|
||||
</div>
|
||||
|
|
@ -226,14 +227,14 @@ export function TrackListRow({
|
|||
<button
|
||||
aria-label={isLiked ? 'Retirer des favoris' : 'Ajouter aux favoris'}
|
||||
onClick={handleLike}
|
||||
className="hover:text-primary transition-colors"
|
||||
className="hover:text-primary transition-colors duration-[var(--duration-normal)]"
|
||||
>
|
||||
{LikeIcon}
|
||||
</button>
|
||||
<button
|
||||
aria-label="Plus d'options"
|
||||
onClick={handleMore}
|
||||
className="hover:text-primary transition-colors"
|
||||
className="hover:text-primary transition-colors duration-[var(--duration-normal)]"
|
||||
>
|
||||
...
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue