style(TrackListSelectionActions): elevate visual fidelity to premium standards
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0e9bcb8e99
commit
6832aeed39
2 changed files with 40 additions and 35 deletions
|
|
@ -4,10 +4,15 @@ import { TrackListSelectionActions } from './TrackListSelectionActions';
|
|||
const meta: Meta<typeof TrackListSelectionActions> = {
|
||||
title: 'Components/Features/Tracks/TrackListSelectionActions',
|
||||
component: TrackListSelectionActions,
|
||||
parameters: {
|
||||
layout: 'padded',
|
||||
},
|
||||
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 flex flex-col justify-end">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
onPlay: { action: 'onPlay' },
|
||||
onDelete: { action: 'onDelete' },
|
||||
|
|
@ -53,3 +58,17 @@ export const PartialActions: Story = {
|
|||
onDelete: () => { },
|
||||
},
|
||||
};
|
||||
|
||||
/** All actions + clear to validate bar and button tokens. */
|
||||
export const VisualStressTest: Story = {
|
||||
args: {
|
||||
selectedCount: 12,
|
||||
selectedTrackIds: Array.from({ length: 12 }, (_, i) => String(i + 1)),
|
||||
onPlay: () => { },
|
||||
onDelete: () => { },
|
||||
onLike: () => { },
|
||||
onDownload: () => { },
|
||||
onMore: () => { },
|
||||
onClearSelection: () => { },
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,21 +53,28 @@ export function TrackListSelectionActions({
|
|||
onMore?.(selectedTrackIds);
|
||||
};
|
||||
|
||||
const actionButtonClass = [
|
||||
'p-2 rounded-[var(--radius-md)]',
|
||||
'transition-[background-color,transform] duration-[var(--duration-normal)]',
|
||||
'hover:bg-primary-foreground/15 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-foreground/40 focus-visible:ring-offset-2 focus-visible:ring-offset-primary',
|
||||
'active:scale-95',
|
||||
].join(' ');
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'fixed bottom-0 left-0 right-0 z-50',
|
||||
'bg-kodo-cyan dark:bg-kodo-cyan text-white',
|
||||
'px-4 py-4 shadow-lg',
|
||||
'bg-primary text-primary-foreground',
|
||||
'px-4 py-4 shadow-lg border-t border-primary-foreground/10 rounded-t-[var(--radius-xl)]',
|
||||
'flex items-center justify-between gap-4',
|
||||
'transition-transform duration-300 ease-in-out',
|
||||
'transition-[opacity,transform,box-shadow] duration-[var(--duration-normal)]',
|
||||
className,
|
||||
)}
|
||||
role="toolbar"
|
||||
aria-label={`Actions pour ${selectedCount} piste${selectedCount > 1 ? 's' : ''} sélectionnée${selectedCount > 1 ? 's' : ''}`}
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm font-medium">
|
||||
<span className="text-sm font-medium tracking-tight text-primary-foreground/95 tabular-nums">
|
||||
{selectedCount} piste{selectedCount > 1 ? 's' : ''} sélectionnée
|
||||
{selectedCount > 1 ? 's' : ''}
|
||||
</span>
|
||||
|
|
@ -77,11 +84,7 @@ export function TrackListSelectionActions({
|
|||
<button
|
||||
type="button"
|
||||
onClick={handlePlay}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-white/5 dark:hover:bg-white/5',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
)}
|
||||
className={actionButtonClass}
|
||||
aria-label={`Lire ${selectedCount} piste${selectedCount > 1 ? 's' : ''}`}
|
||||
>
|
||||
<Play className="h-5 w-5" aria-hidden="true" />
|
||||
|
|
@ -93,11 +96,7 @@ export function TrackListSelectionActions({
|
|||
<button
|
||||
type="button"
|
||||
onClick={handleLike}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-white/5 dark:hover:bg-white/5',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
)}
|
||||
className={actionButtonClass}
|
||||
aria-label={`Ajouter ${selectedCount} piste${selectedCount > 1 ? 's' : ''} aux favoris`}
|
||||
>
|
||||
<Heart className="h-5 w-5" aria-hidden="true" />
|
||||
|
|
@ -109,11 +108,7 @@ export function TrackListSelectionActions({
|
|||
<button
|
||||
type="button"
|
||||
onClick={handleDownload}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-white/5 dark:hover:bg-white/5',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
)}
|
||||
className={actionButtonClass}
|
||||
aria-label={`Télécharger ${selectedCount} piste${selectedCount > 1 ? 's' : ''}`}
|
||||
>
|
||||
<Download className="h-5 w-5" aria-hidden="true" />
|
||||
|
|
@ -126,9 +121,8 @@ export function TrackListSelectionActions({
|
|||
type="button"
|
||||
onClick={handleDelete}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-kodo-red dark:hover:bg-kodo-red',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
actionButtonClass,
|
||||
'hover:bg-destructive/30 focus-visible:ring-destructive/50',
|
||||
)}
|
||||
aria-label={`Supprimer ${selectedCount} piste${selectedCount > 1 ? 's' : ''}`}
|
||||
>
|
||||
|
|
@ -141,11 +135,7 @@ export function TrackListSelectionActions({
|
|||
<button
|
||||
type="button"
|
||||
onClick={handleMore}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-white/5 dark:hover:bg-white/5',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
)}
|
||||
className={actionButtonClass}
|
||||
aria-label={`Plus d'options pour ${selectedCount} piste${selectedCount > 1 ? 's' : ''}`}
|
||||
>
|
||||
<MoreVertical className="h-5 w-5" aria-hidden="true" />
|
||||
|
|
@ -159,11 +149,7 @@ export function TrackListSelectionActions({
|
|||
<button
|
||||
type="button"
|
||||
onClick={onClearSelection}
|
||||
className={cn(
|
||||
'p-2 rounded-md transition-colors',
|
||||
'hover:bg-white/5 dark:hover:bg-white/5',
|
||||
'focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-blue-600',
|
||||
)}
|
||||
className={actionButtonClass}
|
||||
aria-label="Désélectionner toutes les pistes"
|
||||
>
|
||||
<X className="h-5 w-5" aria-hidden="true" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue