# Loading States Pattern Guide ## FE-COMP-001: Add loading states to all async operations This document outlines the patterns and best practices for adding loading states to async operations in the Veza frontend. ## Components Available ### 1. LoadingSpinner Located at `@/components/ui/loading-spinner` ```tsx import { LoadingSpinner } from '@/components/ui/loading-spinner'; ; ``` ### 2. Skeleton Located at `@/components/ui/skeleton` ```tsx import { Skeleton } from '@/components/ui/skeleton'; ; ``` ### 3. ButtonLoading Located at `@/components/ui/button-loading` ```tsx import { ButtonLoading } from '@/components/ui/button-loading'; Submit ; ``` ## Patterns ### Pattern 1: Form Submissions Always disable the submit button and show a loading indicator during submission: ```tsx const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { await submitForm(); } finally { setIsSubmitting(false); } }; ; ``` ### Pattern 2: Data Fetching with TanStack Query Use `isLoading` from `useQuery`: ```tsx const { data, isLoading, error } = useQuery({ queryKey: ['key'], queryFn: fetchData, }); if (isLoading) { return ; } ``` ### Pattern 3: Mutations with TanStack Query Use `isPending` from `useMutation`: ```tsx const mutation = useMutation({ mutationFn: updateData, }); ; ``` ### Pattern 4: Skeleton Loaders for Lists Use skeleton loaders while data is loading: ```tsx if (isLoading) { return (
{Array.from({ length: 5 }).map((_, i) => ( ))}
); } ``` ### Pattern 5: Inline Loading States For operations that don't block the entire UI: ```tsx ``` ## Checklist When implementing async operations, ensure: - [ ] Button is disabled during operation - [ ] Loading indicator is visible (spinner or skeleton) - [ ] Loading text/state is clear to user - [ ] Error states are handled - [ ] Success states provide feedback - [ ] Form inputs are disabled during submission (if applicable) - [ ] Navigation is prevented during critical operations ## Examples in Codebase - `PlaylistForm.tsx` - Form submission with loading state - `FollowButton.tsx` - Inline loading state - `AddCollaboratorModal.tsx` - Mutation with loading state - `NotificationsPage.tsx` - Query with loading state - `SearchPage.tsx` - Multiple queries with loading states