2025-12-03 21:56:50 +00:00
|
|
|
/**
|
|
|
|
|
* Composant NextPreviousButtons
|
|
|
|
|
* Boutons pour naviguer dans la queue (next/previous)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { SkipBack, SkipForward } from 'lucide-react';
|
|
|
|
|
import { cn } from '@/lib/utils';
|
|
|
|
|
|
|
|
|
|
export interface NextPreviousButtonsProps {
|
|
|
|
|
onNext: () => void;
|
|
|
|
|
onPrevious: () => void;
|
|
|
|
|
canGoNext: boolean;
|
|
|
|
|
canGoPrevious: boolean;
|
|
|
|
|
size?: 'sm' | 'md' | 'lg';
|
|
|
|
|
variant?: 'default' | 'ghost' | 'outline';
|
|
|
|
|
className?: string;
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function NextPreviousButtons({
|
|
|
|
|
onNext,
|
|
|
|
|
onPrevious,
|
|
|
|
|
canGoNext,
|
|
|
|
|
canGoPrevious,
|
|
|
|
|
size = 'md',
|
|
|
|
|
variant = 'ghost',
|
|
|
|
|
className,
|
|
|
|
|
disabled = false,
|
|
|
|
|
}: NextPreviousButtonsProps) {
|
|
|
|
|
const sizeClasses = {
|
|
|
|
|
sm: 'h-8 w-8',
|
|
|
|
|
md: 'h-10 w-10',
|
|
|
|
|
lg: 'h-12 w-12',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const iconSizes = {
|
|
|
|
|
sm: 'h-4 w-4',
|
|
|
|
|
md: 'h-5 w-5',
|
|
|
|
|
lg: 'h-6 w-6',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const variantClasses = {
|
|
|
|
|
default:
|
|
|
|
|
'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500 dark:bg-blue-500 dark:hover:bg-blue-600',
|
|
|
|
|
ghost:
|
|
|
|
|
'bg-transparent text-gray-700 hover:bg-gray-100 focus:ring-gray-500 dark:text-gray-300 dark:hover:bg-gray-800',
|
|
|
|
|
outline:
|
|
|
|
|
'border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 focus:ring-gray-500 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isPreviousDisabled = disabled || !canGoPrevious;
|
|
|
|
|
const isNextDisabled = disabled || !canGoNext;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={cn('flex items-center gap-2', className)}>
|
|
|
|
|
{/* Previous Button */}
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onPrevious}
|
|
|
|
|
disabled={isPreviousDisabled}
|
|
|
|
|
className={cn(
|
|
|
|
|
'rounded-full flex items-center justify-center transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
|
|
|
sizeClasses[size],
|
|
|
|
|
variantClasses[variant],
|
2025-12-13 02:34:34 +00:00
|
|
|
isPreviousDisabled && 'opacity-50 cursor-not-allowed',
|
2025-12-03 21:56:50 +00:00
|
|
|
)}
|
|
|
|
|
aria-label="Piste précédente"
|
|
|
|
|
aria-disabled={isPreviousDisabled}
|
|
|
|
|
>
|
|
|
|
|
<SkipBack className={iconSizes[size]} aria-hidden="true" />
|
|
|
|
|
<span className="sr-only">Piste précédente</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{/* Next Button */}
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onNext}
|
|
|
|
|
disabled={isNextDisabled}
|
|
|
|
|
className={cn(
|
|
|
|
|
'rounded-full flex items-center justify-center transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
|
|
|
sizeClasses[size],
|
|
|
|
|
variantClasses[variant],
|
2025-12-13 02:34:34 +00:00
|
|
|
isNextDisabled && 'opacity-50 cursor-not-allowed',
|
2025-12-03 21:56:50 +00:00
|
|
|
)}
|
|
|
|
|
aria-label="Piste suivante"
|
|
|
|
|
aria-disabled={isNextDisabled}
|
|
|
|
|
>
|
|
|
|
|
<SkipForward className={iconSizes[size]} aria-hidden="true" />
|
|
|
|
|
<span className="sr-only">Piste suivante</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default NextPreviousButtons;
|