Implemented comprehensive loading and error handling components for the WellNuo web application with full test coverage. Components added: - LoadingSpinner: Configurable spinner with sizes, colors, and variants * LoadingOverlay: Full-screen loading with backdrop options * InlineLoader: Small inline spinner for buttons * PageLoader: Full-page centered loading state - ErrorMessage: Inline error messages with severity levels * FullScreenError: Full-page error states with retry/back actions * FieldError: Form field validation errors * ErrorBoundaryFallback: Error boundary fallback component * EmptyState: Empty data state component - Skeleton: Animated loading skeletons * SkeletonAvatar: Circular avatar skeleton * SkeletonText: Multi-line text skeleton * SkeletonCard: Card-style skeleton * SkeletonList: List of skeleton cards * SkeletonTable: Table skeleton with rows/columns * SkeletonDashboard: Dashboard-style skeleton layout * SkeletonForm: Form skeleton with fields Technical details: - Tailwind CSS styling with cn() utility function - Full accessibility support (ARIA labels, roles) - Comprehensive test coverage (57 tests, all passing) - TypeScript strict mode compliance - Added clsx and tailwind-merge dependencies Files: - web/components/ui/LoadingSpinner.tsx - web/components/ui/ErrorMessage.tsx - web/components/ui/Skeleton.tsx - web/components/ui/index.ts - web/lib/utils.ts - web/components/ui/__tests__/*.test.tsx 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
22 lines
532 B
TypeScript
22 lines
532 B
TypeScript
/**
|
|
* Utility functions for the web application
|
|
*/
|
|
|
|
import { type ClassValue, clsx } from 'clsx';
|
|
import { twMerge } from 'tailwind-merge';
|
|
|
|
/**
|
|
* Merge Tailwind CSS classes with proper precedence
|
|
*
|
|
* Uses clsx for conditional classes and tailwind-merge to handle conflicts
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* cn('bg-red-500', isActive && 'bg-blue-500') // 'bg-blue-500' if active
|
|
* cn('p-4', className) // Merges with user-provided className
|
|
* ```
|
|
*/
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return twMerge(clsx(inputs));
|
|
}
|