veza/apps/web/src/components/ui/empty-state.tsx

75 lines
1.7 KiB
TypeScript
Raw Normal View History

import { ReactNode } from 'react';
import { Button } from './button';
import { Card, CardContent } from './card';
import { cn } from '@/lib/utils';
// FE-COMP-003: Add empty states to all list views
export interface EmptyStateProps {
icon?: ReactNode;
title: string;
description?: string;
action?: {
label: string;
onClick: () => void;
variant?: 'default' | 'outline' | 'ghost';
};
className?: string;
size?: 'sm' | 'md' | 'lg';
}
/**
* EmptyState - Composant réutilisable pour afficher des états vides dans les listes
* FE-COMP-003: Add empty states to all list views
*/
export function EmptyState({
icon,
title,
description,
action,
className,
size = 'md',
}: EmptyStateProps) {
const sizeClasses = {
sm: 'py-6',
md: 'py-12',
lg: 'py-16',
};
const iconSizeClasses = {
sm: 'h-8 w-8',
md: 'h-12 w-12',
lg: 'h-16 w-16',
};
return (
<Card className={cn(className)}>
<CardContent className={cn('text-center', sizeClasses[size])}>
{icon && (
<div className="flex justify-center mb-4">
<div className={cn('text-muted-foreground', iconSizeClasses[size])}>
{icon}
</div>
</div>
)}
<h3 className="text-lg font-semibold mb-2">{title}</h3>
{description && (
<p className="text-sm text-muted-foreground mb-4 max-w-md mx-auto">
{description}
</p>
)}
{action && (
<Button
onClick={action.onClick}
variant={action.variant || 'default'}
size={size === 'sm' ? 'sm' : 'default'}
>
{action.label}
</Button>
)}
</CardContent>
</Card>
);
}