Replace legacy text-kodo-cyan/border-kodo-cyan/bg-kodo-cyan with semantic text-primary/border-primary/bg-primary across 51 components. The brand primary color now uses the design system token, enabling proper theme adaptation. Covers UI primitives, search, dashboard, chat, playlists, settings, social, marketplace, and auth components. Co-authored-by: Cursor <cursoragent@cursor.com>
108 lines
2.5 KiB
TypeScript
108 lines
2.5 KiB
TypeScript
import { Loader2 } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
/**
|
|
* SpinnerProps - Propriétés du composant Spinner
|
|
*
|
|
* @interface SpinnerProps
|
|
*/
|
|
export interface SpinnerProps {
|
|
/**
|
|
* Taille du spinner
|
|
*
|
|
* - `sm`: Petit (h-4 w-4) - pour les boutons et éléments compacts
|
|
* - `md`: Moyen (h-5 w-5) - par défaut
|
|
* - `lg`: Grand (h-6 w-6) - pour les éléments plus grands
|
|
*
|
|
* @default 'md'
|
|
*/
|
|
size?: 'sm' | 'md' | 'lg';
|
|
|
|
/**
|
|
* Couleur du spinner
|
|
*
|
|
* - `default`: Couleur par défaut (kodo-cyan pour le thème Kodo)
|
|
* - `muted`: Couleur atténuée (text-muted-foreground)
|
|
* - `white`: Blanc
|
|
* - `current`: Utilise la couleur du texte parent
|
|
*
|
|
* @default 'default'
|
|
*/
|
|
variant?: 'default' | 'muted' | 'white' | 'current';
|
|
|
|
/**
|
|
* Classes CSS personnalisées
|
|
*/
|
|
className?: string;
|
|
|
|
/**
|
|
* Label d'accessibilité
|
|
*
|
|
* @default 'Chargement en cours'
|
|
*/
|
|
'aria-label'?: string;
|
|
}
|
|
|
|
/**
|
|
* Spinner - Composant de spinner réutilisable pour les états de chargement inline
|
|
*
|
|
* Composant de spinner optimisé pour l'utilisation inline dans les boutons,
|
|
* formulaires et autres éléments UI. Utilise le design system Kodo.
|
|
*
|
|
* Différences avec LoadingSpinner:
|
|
* - LoadingSpinner: Pour les états de chargement de page complète avec conteneur
|
|
* - Spinner: Pour les spinners inline dans les boutons et éléments UI
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* // Spinner simple dans un bouton
|
|
* <Button disabled={isLoading}>
|
|
* {isLoading && <Spinner size="sm" className="mr-2" />}
|
|
* Enregistrer
|
|
* </Button>
|
|
*
|
|
* // Spinner avec couleur personnalisée
|
|
* <Spinner size="lg" variant="muted" />
|
|
*
|
|
* // Spinner avec classes personnalisées
|
|
* <Spinner className="text-primary" />
|
|
* ```
|
|
*
|
|
* @component
|
|
* @param {SpinnerProps} props - Propriétés du composant
|
|
* @returns {JSX.Element} Spinner animé
|
|
*/
|
|
export function Spinner({
|
|
size = 'md',
|
|
variant = 'default',
|
|
className,
|
|
'aria-label': ariaLabel = 'Chargement en cours',
|
|
}: SpinnerProps) {
|
|
const sizeClasses = {
|
|
sm: 'h-4 w-4',
|
|
md: 'h-5 w-5',
|
|
lg: 'h-6 w-6',
|
|
};
|
|
|
|
const variantClasses = {
|
|
default: 'text-primary',
|
|
muted: 'text-muted-foreground',
|
|
white: 'text-white',
|
|
current: 'text-current',
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Loader2
|
|
className={cn(
|
|
'animate-spin',
|
|
sizeClasses[size],
|
|
variantClasses[variant],
|
|
className,
|
|
)}
|
|
aria-hidden="true"
|
|
/>
|
|
<span className="sr-only">{ariaLabel}</span>
|
|
</>
|
|
);
|
|
}
|