Claude Agent Skill · by Sickn33

React Ui Patterns

Install React Ui Patterns skill for Claude Code from sickn33/antigravity-awesome-skills.

Install
Terminal · npx
$npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill react-ui-patterns
Works with Paperclip

How React Ui Patterns fits into a Paperclip company.

React Ui Patterns drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md300 lines
Expand
---name: react-ui-patternsdescription: "Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states."risk: unknownsource: communitydate_added: "2026-02-27"--- # React UI Patterns ## Core Principles 1. **Never show stale UI** - Loading spinners only when actually loading2. **Always surface errors** - Users must know when something fails3. **Optimistic updates** - Make the UI feel instant4. **Progressive disclosure** - Show content as it becomes available5. **Graceful degradation** - Partial data is better than no data ## Loading State Patterns ### The Golden Rule **Show loading indicator ONLY when there's no data to display.** ```typescript// CORRECT - Only show loading when no data existsconst { data, loading, error } = useGetItemsQuery(); if (error) return <ErrorState error={error} onRetry={refetch} />;if (loading && !data) return <LoadingState />;if (!data?.items.length) return <EmptyState />; return <ItemList items={data.items} />;``` ```typescript// WRONG - Shows spinner even when we have cached dataif (loading) return <LoadingState />; // Flashes on refetch!``` ### Loading State Decision Tree ```Is there an error?  → Yes: Show error state with retry option  → No: Continue Is it loading AND we have no data?  → Yes: Show loading indicator (spinner/skeleton)  → No: Continue Do we have data?  → Yes, with items: Show the data  → Yes, but empty: Show empty state  → No: Show loading (fallback)``` ### Skeleton vs Spinner | Use Skeleton When | Use Spinner When ||-------------------|------------------|| Known content shape | Unknown content shape || List/card layouts | Modal actions || Initial page load | Button submissions || Content placeholders | Inline operations | ## Error Handling Patterns ### The Error Handling Hierarchy ```1. Inline error (field-level) → Form validation errors2. Toast notification → Recoverable errors, user can retry3. Error banner → Page-level errors, data still partially usable4. Full error screen → Unrecoverable, needs user action``` ### Always Show Errors **CRITICAL: Never swallow errors silently.** ```typescript// CORRECT - Error always surfaced to userconst [createItem, { loading }] = useCreateItemMutation({  onCompleted: () => {    toast.success({ title: 'Item created' });  },  onError: (error) => {    console.error('createItem failed:', error);    toast.error({ title: 'Failed to create item' });  },}); // WRONG - Error silently caught, user has no ideaconst [createItem] = useCreateItemMutation({  onError: (error) => {    console.error(error); // User sees nothing!  },});``` ### Error State Component Pattern ```typescriptinterface ErrorStateProps {  error: Error;  onRetry?: () => void;  title?: string;} const ErrorState = ({ error, onRetry, title }: ErrorStateProps) => (  <div className="error-state">    <Icon name="exclamation-circle" />    <h3>{title ?? 'Something went wrong'}</h3>    <p>{error.message}</p>    {onRetry && (      <Button onClick={onRetry}>Try Again</Button>    )}  </div>);``` ## Button State Patterns ### Button Loading State ```tsx<Button  onClick={handleSubmit}  isLoading={isSubmitting}  disabled={!isValid || isSubmitting}>  Submit</Button>``` ### Disable During Operations **CRITICAL: Always disable triggers during async operations.** ```tsx// CORRECT - Button disabled while loading<Button  disabled={isSubmitting}  isLoading={isSubmitting}  onClick={handleSubmit}>  Submit</Button> // WRONG - User can tap multiple times<Button onClick={handleSubmit}>  {isSubmitting ? 'Submitting...' : 'Submit'}</Button>``` ## Empty States ### Empty State Requirements Every list/collection MUST have an empty state: ```tsx// WRONG - No empty statereturn <FlatList data={items} />; // CORRECT - Explicit empty statereturn (  <FlatList    data={items}    ListEmptyComponent={<EmptyState />}  />);``` ### Contextual Empty States ```tsx// Search with no results<EmptyState  icon="search"  title="No results found"  description="Try different search terms"/> // List with no items yet<EmptyState  icon="plus-circle"  title="No items yet"  description="Create your first item"  action={{ label: 'Create Item', onClick: handleCreate }}/>``` ## Form Submission Pattern ```tsxconst MyForm = () => {  const [submit, { loading }] = useSubmitMutation({    onCompleted: handleSuccess,    onError: handleError,  });   const handleSubmit = async () => {    if (!isValid) {      toast.error({ title: 'Please fix errors' });      return;    }    await submit({ variables: { input: values } });  };   return (    <form>      <Input        value={values.name}        onChange={handleChange('name')}        error={touched.name ? errors.name : undefined}      />      <Button        type="submit"        onClick={handleSubmit}        disabled={!isValid || loading}        isLoading={loading}      >        Submit      </Button>    </form>  );};``` ## Anti-Patterns ### Loading States ```typescript// WRONG - Spinner when data exists (causes flash)if (loading) return <Spinner />; // CORRECT - Only show loading without dataif (loading && !data) return <Spinner />;``` ### Error Handling ```typescript// WRONG - Error swallowedtry {  await mutation();} catch (e) {  console.log(e); // User has no idea!} // CORRECT - Error surfacedonError: (error) => {  console.error('operation failed:', error);  toast.error({ title: 'Operation failed' });}``` ### Button States ```typescript// WRONG - Button not disabled during submission<Button onClick={submit}>Submit</Button> // CORRECT - Disabled and shows loading<Button onClick={submit} disabled={loading} isLoading={loading}>  Submit</Button>``` ## Checklist Before completing any UI component: **UI States:**- [ ] Error state handled and shown to user- [ ] Loading state shown only when no data exists- [ ] Empty state provided for collections- [ ] Buttons disabled during async operations- [ ] Buttons show loading indicator when appropriate **Data & Mutations:**- [ ] Mutations have onError handler- [ ] All user actions have feedback (toast/visual) ## Integration with Other Skills - **graphql-schema**: Use mutation patterns with proper error handling- **testing-patterns**: Test all UI states (loading, error, empty, success)- **formik-patterns**: Apply form submission patterns ## When to UseThis skill is applicable to execute the workflow or actions described in the overview. ## Limitations- Use this skill only when the task clearly matches the scope described above.- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.