veza/apps/web/src/components/ui/empty-state.tsx
senke f16a8dc030 [FE-COMP-003] fe-comp: Add empty states to all list views
- Created reusable EmptyState component with icon, title, description, and action support
- Improved empty state in PlaylistList with better messaging and icons
- Improved empty states in UserProfilePage for tracks and playlists tabs
- Added contextual messages based on whether viewing own profile or others
- Added helpful descriptions and icons to all empty states
- Empty states now provide clear guidance on what users can do next
- All list views now have consistent and helpful empty state messaging
2025-12-24 14:33:20 +01:00

74 lines
1.7 KiB
TypeScript

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