ui: create BulkModeBanner component (Action 8.4.1.1)
- Created reusable BulkModeBanner component for bulk selection mode - Displays selected item count with proper French pluralization - Uses Kodo design system (cyan theme, consistent styling) - Includes close button to exit bulk mode - Accessibility: role="status", aria-live="polite", aria-atomic="true" - Follows existing component patterns (similar to Alert component) - Component returns null when inactive or no items selected - Part of Action 8.4.1.1: Create bulk mode banner component
This commit is contained in:
parent
8a90a08f69
commit
849fb6d464
1 changed files with 96 additions and 0 deletions
96
apps/web/src/components/BulkModeBanner.tsx
Normal file
96
apps/web/src/components/BulkModeBanner.tsx
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import { X, CheckSquare } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
/**
|
||||
* BulkModeBannerProps - Propriétés du composant BulkModeBanner
|
||||
*/
|
||||
export interface BulkModeBannerProps {
|
||||
/**
|
||||
* Si true, le banner est affiché
|
||||
*/
|
||||
isActive: boolean;
|
||||
|
||||
/**
|
||||
* Nombre d'éléments sélectionnés
|
||||
*/
|
||||
selectedCount: number;
|
||||
|
||||
/**
|
||||
* Fonction appelée lors du clic sur le bouton de fermeture
|
||||
* Doit désactiver le mode bulk et réinitialiser la sélection
|
||||
*/
|
||||
onClose: () => void;
|
||||
|
||||
/**
|
||||
* Classes CSS personnalisées
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* BulkModeBanner - Banner pour le mode sélection multiple
|
||||
*
|
||||
* Affiche un banner informatif lorsque le mode bulk est actif,
|
||||
* montrant le nombre d'éléments sélectionnés et permettant
|
||||
* de fermer le mode bulk.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <BulkModeBanner
|
||||
* isActive={isBulkMode}
|
||||
* selectedCount={selectedTracks.size}
|
||||
* onClose={() => {
|
||||
* setIsBulkMode(false);
|
||||
* setSelectedTracks(new Set());
|
||||
* }}
|
||||
* />
|
||||
* ```
|
||||
*
|
||||
* @component
|
||||
* @param {BulkModeBannerProps} props - Propriétés du composant
|
||||
* @returns {JSX.Element | null} Banner ou null si isActive est false
|
||||
*/
|
||||
export function BulkModeBanner({
|
||||
isActive,
|
||||
selectedCount,
|
||||
onClose,
|
||||
className,
|
||||
}: BulkModeBannerProps) {
|
||||
if (!isActive || selectedCount === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const itemText =
|
||||
selectedCount === 1 ? 'élément sélectionné' : 'éléments sélectionnés';
|
||||
|
||||
return (
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
className={cn(
|
||||
'w-full bg-kodo-cyan/10 border-b border-kodo-cyan/30 text-kodo-cyan',
|
||||
'px-4 py-3 flex items-center justify-between gap-4',
|
||||
'transition-all duration-300',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-3 flex-1 min-w-0">
|
||||
<CheckSquare className="w-5 h-5 flex-shrink-0" aria-hidden="true" />
|
||||
<span className="text-sm font-medium">
|
||||
<span className="font-bold">{selectedCount}</span> {itemText}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={onClose}
|
||||
className="text-kodo-cyan hover:text-kodo-cyan hover:bg-kodo-cyan/20 h-auto py-1 px-2 flex-shrink-0"
|
||||
aria-label="Fermer le mode sélection"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue