smithery/doanchienthangdev

designing-frontend-patterns

Claude designs scalable React component architectures using compound components, custom hooks, and state machines. Use when building reusable UI systems or complex component APIs.

Installation

$ npx skills add smithery/doanchienthangdev --skill designing-frontend-patterns

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/doanchienthangdev · top by installs.

npx skills add smithery/doanchienthangdev

Browse all from smithery/doanchienthangdev

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,490 B
  • docs SUMMARY.md 214 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Designing Frontend Patterns

Quick Start

// Compound component pattern with context
const SelectContext = createContext<SelectContextValue | null>(null);

export function Select({ children, value, onValueChange }: SelectProps) {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <SelectContext.Provider value={{ isOpen, setIsOpen, value, onValueChange }}>
      <div className="relative">{children}</div>
    </SelectContext.Provider>
  );
}

Select.Trigger = SelectTrigger;
Select.Content = SelectContent;
Select.Item = SelectItem;

Features

Feature Description Guide
Compound Components Shared state via context for flexible component APIs ref/compound-components.md
Custom Hooks Encapsulate reusable logic (useDebounce, useLocalStorage) ref/custom-hooks.md
Render Props Maximum flexibility for data fetching and rendering ref/render-props.md
State Machines Predictable state transitions for complex flows ref/state-machines.md
HOCs Cross-cutting concerns (auth, error boundaries) ref/higher-order-components.md
Optimistic UI Instant feedback with rollback on failure ref/optimistic-updates.md

Common Patterns

Custom Hook with Cleanup

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

export function useLocalStorage<T>(key: string, initialValue: T) {
  const [stored, setStored] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch { return initialValue; }
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(stored));
  }, [key, stored]);

  return [stored, setStored] as const;
}

State Machine Pattern

type FormState = 'idle' | 'validating' | 'submitting' | 'success' | 'error';
type FormEvent =
  | { type: 'SUBMIT'; data: FormData }
  | { type: 'SUCCESS'; response: any }
  | { type: 'ERROR'; error: string };

function useFormMachine() {
  const [state, setState] = useState<FormState>('idle');
  const [context, setContext] = useState({ data: null, error: null });

  const send = useCallback((event: FormEvent) => {
    switch (state) {
      case 'idle':
        if (event.type === 'SUBMIT') { setState('validating'); }
        break;
      case 'submitting':
        if (event.type === 'SUCCESS') { setState('success'); }
        if (event.type === 'ERROR') { setState('error'); setContext(c => ({ ...c, error: event.error })); }
        break;
    }
  }, [state]);

  return { state, context, send };
}

Optimistic Update Hook

export function useOptimistic<T>(initialData: T, reducer: (state: T, action: any) => T) {
  const [state, setState] = useState({ data: initialData, pending: false, error: null });
  const previousRef = useRef(initialData);

  const optimisticUpdate = useCallback(async (action: any, asyncOp: () => Promise<T>) => {
    previousRef.current = state.data;
    setState({ data: reducer(state.data, action), pending: true, error: null });

    try {
      const result = await asyncOp();
      setState({ data: result, pending: false, error: null });
    } catch (error) {
      setState({ data: previousRef.current, pending: false, error: error as Error });
    }
  }, [state.data, reducer]);

  return { ...state, optimisticUpdate };
}

Best Practices

Do Avoid
Use compound components for complex UI with shared state Overusing HOCs (prefer hooks)
Create custom hooks to encapsulate reusable logic Mutating state directly
Implement state machines for complex state transitions Deeply nested component hierarchies
Use TypeScript for type-safe component APIs Passing too many props (use context/composition)
Use forwardRef for component library primitives Creating components with side effects in render
Keep components focused with single responsibility Prop drilling for deeply nested data