veza/apps/web/src/components/ui/Spinner.tsx
senke 1e897c95a0 ui(tokens): migrate kodo-cyan to primary (51 files, 88 instances)
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>
2026-02-09 00:19:12 +01:00

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>
</>
);
}