R

React Ui Patterns Engine

Battle-tested skill for modern, react, patterns, loading. Includes structured workflows, validation checks, and reusable patterns for development.

SkillClipticsdevelopmentv1.0.0MIT
0 views0 copies

React UI Patterns Engine

A practical skill for building robust React user interfaces with proper loading states, error handling, optimistic updates, form management, and accessible interactive components. Focused on UI correctness rather than architecture.

When to Use This Skill

Choose this skill when:

  • Building interactive UI components that handle loading, error, and empty states
  • Implementing forms with validation, submission, and error recovery
  • Creating accessible modals, dropdowns, tooltips, and popovers
  • Adding toast notifications, skeleton loaders, and progressive disclosure
  • Handling pagination, infinite scroll, and virtualized lists

Consider alternatives when:

  • Designing application architecture → use a React patterns skill
  • Building a component library from scratch → use a design system skill
  • Working on data fetching strategy → use a data fetching skill
  • Optimizing bundle performance → use a performance profiling skill

Quick Start

# Install common UI dependencies npm install @radix-ui/react-dialog @radix-ui/react-toast npm install react-hook-form zod @hookform/resolvers
// Robust async UI component with all states handled function UserList() { const { data, loading, error, retry } = useFetch<User[]>('/api/users'); if (loading) return <SkeletonList count={5} />; if (error) return <ErrorCard message={error.message} onRetry={retry} />; if (!data?.length) return <EmptyState icon="users" message="No users yet" />; return ( <ul role="list"> {data.map(user => ( <UserCard key={user.id} user={user} /> ))} </ul> ); }

Core Concepts

UI State Machine

StateVisualUser ActionTransition
idleDefault UITrigger action→ loading
loadingSkeleton/spinnerCancel (optional)→ success or error
successData renderedInteract→ idle
errorError message + retryClick retry→ loading
emptyEmpty state illustrationCreate new→ loading

Form Pattern with Validation

import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; const schema = z.object({ email: z.string().email('Invalid email address'), password: z.string().min(8, 'Password must be at least 8 characters'), role: z.enum(['admin', 'editor', 'viewer']), }); type FormData = z.infer<typeof schema>; function CreateUserForm({ onSubmit }: { onSubmit: (data: FormData) => Promise<void> }) { const { register, handleSubmit, formState: { errors, isSubmitting }, setError, } = useForm<FormData>({ resolver: zodResolver(schema) }); const submit = async (data: FormData) => { try { await onSubmit(data); } catch (err: any) { setError('root', { message: err.message || 'Submission failed' }); } }; return ( <form onSubmit={handleSubmit(submit)} noValidate> <Field label="Email" error={errors.email?.message}> <input type="email" {...register('email')} aria-invalid={!!errors.email} /> </Field> <Field label="Password" error={errors.password?.message}> <input type="password" {...register('password')} aria-invalid={!!errors.password} /> </Field> {errors.root && <Alert variant="error">{errors.root.message}</Alert>} <button type="submit" disabled={isSubmitting}> {isSubmitting ? 'Creating...' : 'Create User'} </button> </form> ); }

Accessible Modal Pattern

function Modal({ open, onClose, title, children }: ModalProps) { const overlayRef = useRef<HTMLDivElement>(null); useEffect(() => { if (!open) return; const prev = document.activeElement as HTMLElement; document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = ''; prev?.focus(); }; }, [open]); if (!open) return null; return createPortal( <div ref={overlayRef} className="modal-overlay" onClick={e => e.target === overlayRef.current && onClose()} role="presentation"> <div role="dialog" aria-modal="true" aria-label={title}> <h2>{title}</h2> {children} <button onClick={onClose} aria-label="Close">Ɨ</button> </div> </div>, document.body ); }

Configuration

ParameterTypeDefaultDescription
skeletonAnimationstring'pulse'Animation style: pulse, wave, or none
toastDurationnumber5000Auto-dismiss time for toast notifications (ms)
toastPositionstring'bottom-right'Toast container position on screen
formResetOnSuccessbooleantrueReset form fields after successful submission
modalCloseOnOverlaybooleantrueClose modal when clicking overlay backdrop
infiniteScrollThresholdnumber200Pixel distance from bottom to trigger next page load

Best Practices

  1. Never show stale UI without indication — If cached data is displayed while fresh data loads, show a subtle indicator (dimmed content or top progress bar). Users should always know whether they're seeing current or cached information.

  2. Always surface errors visibly — Failed API calls must produce visible user feedback — inline error messages, toast notifications, or error cards with retry buttons. Silent failures cause confusion and data loss.

  3. Use skeleton screens instead of spinners for layout-stable content — Skeletons preserve layout dimensions and reduce perceived loading time. Reserve spinners for actions where content dimensions are unknown.

  4. Implement keyboard navigation for all interactive components — Modals need focus trapping, dropdowns need arrow key navigation, custom selects need type-ahead search. Test with keyboard-only navigation before considering a component complete.

  5. Debounce user inputs that trigger expensive operations — Search inputs, filter changes, and resize handlers should be debounced (typically 300ms for search, 150ms for filters). This prevents unnecessary API calls and improves responsiveness.

Common Issues

Modal focus not returning after close — When a modal opens, store a reference to document.activeElement. On close, call .focus() on that stored element. Without this, keyboard users lose their place in the page after every modal interaction.

Toast notifications stacking and overflowing — Without a maximum count, rapid events can spawn dozens of toasts that obscure content. Limit visible toasts to 3-5, queue additional ones, and always provide a manual dismiss button alongside auto-dismiss timers.

Infinite scroll loading duplicates — Race conditions between scroll events and API responses cause the same page to load multiple times. Use a loading flag ref (not state) to gate fetch calls, and deduplicate by ID before appending new items to the list.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates