--- name: senior-frontend description: Expert frontend development with React, Vue, and modern frameworks including component architecture, state management, performance optimization, and accessibility. version: 1.0.0 author: Claude Skills category: engineering tags: [frontend, react, vue, typescript, css, accessibility] --- # Senior Frontend Developer Expert-level frontend development for modern web applications. ## Core Competencies - Component architecture - State management - Performance optimization - Accessibility (a11y) - CSS architecture - Build optimization - Testing strategies - Design system implementation ## Framework Comparison | Feature | React | Vue | Svelte | |---------|-------|-----|--------| | Learning Curve | Medium | Low | Low | | Bundle Size | Medium | Small | Smallest | | Ecosystem | Largest | Large | Growing | | Performance | Excellent | Excellent | Best | | Enterprise Use | Highest | High | Medium | ## React Patterns ### Component Patterns **Presentational Component:** ```typescript interface ButtonProps { variant: 'primary' | 'secondary'; size: 'sm' | 'md' | 'lg'; disabled?: boolean; children: React.ReactNode; onClick?: () => void; } export function Button({ variant, size, disabled, children, onClick }: ButtonProps) { return ( ); } ``` **Container Component:** ```typescript export function UserListContainer() { const { data: users, isLoading, error } = useUsers(); if (isLoading) return ; if (error) return ; return ; } ``` **Higher-Order Component:** ```typescript function withAuth

(Component: React.ComponentType

) { return function AuthenticatedComponent(props: P) { const { user, isLoading } = useAuth(); if (isLoading) return ; if (!user) return ; return ; }; } ``` ### Custom Hooks **Data Fetching Hook:** ```typescript function useApi(url: string, options?: RequestInit) { const [data, setData] = useState(null); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const controller = new AbortController(); async function fetchData() { try { setIsLoading(true); const response = await fetch(url, { ...options, signal: controller.signal, }); if (!response.ok) throw new Error('Request failed'); const json = await response.json(); setData(json); } catch (err) { if (err.name !== 'AbortError') { setError(err as Error); } } finally { setIsLoading(false); } } fetchData(); return () => controller.abort(); }, [url]); return { data, error, isLoading }; } ``` **Local Storage Hook:** ```typescript function useLocalStorage(key: string, initialValue: T) { const [storedValue, setStoredValue] = useState(() => { if (typeof window === 'undefined') return initialValue; try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch { return initialValue; } }); const setValue = (value: T | ((val: T) => T)) => { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); }; return [storedValue, setValue] as const; } ``` ## State Management ### Zustand ```typescript import { create } from 'zustand'; import { persist } from 'zustand/middleware'; interface CartStore { items: CartItem[]; addItem: (item: CartItem) => void; removeItem: (id: string) => void; clearCart: () => void; total: () => number; } export const useCartStore = create()( persist( (set, get) => ({ items: [], addItem: (item) => set((state) => ({ items: [...state.items, item], })), removeItem: (id) => set((state) => ({ items: state.items.filter((item) => item.id !== id), })), clearCart: () => set({ items: [] }), total: () => get().items.reduce((sum, item) => sum + item.price * item.quantity, 0), }), { name: 'cart-storage' } ) ); ``` ### React Query ```typescript import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; // Query function useProducts(category: string) { return useQuery({ queryKey: ['products', category], queryFn: () => fetchProducts(category), staleTime: 5 * 60 * 1000, }); } // Mutation function useCreateProduct() { const queryClient = useQueryClient(); return useMutation({ mutationFn: createProduct, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); } // Optimistic Update function useUpdateProduct() { const queryClient = useQueryClient(); return useMutation({ mutationFn: updateProduct, onMutate: async (newProduct) => { await queryClient.cancelQueries({ queryKey: ['products', newProduct.id] }); const previous = queryClient.getQueryData(['products', newProduct.id]); queryClient.setQueryData(['products', newProduct.id], newProduct); return { previous }; }, onError: (err, newProduct, context) => { queryClient.setQueryData(['products', newProduct.id], context?.previous); }, onSettled: (data, error, variables) => { queryClient.invalidateQueries({ queryKey: ['products', variables.id] }); }, }); } ``` ## CSS Architecture ### Tailwind CSS Best Practices **Component Classes:** ```typescript const buttonVariants = cva( 'inline-flex items-center justify-center rounded-md font-medium transition-colors', { variants: { variant: { primary: 'bg-blue-600 text-white hover:bg-blue-700', secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300', outline: 'border border-gray-300 hover:bg-gray-100', }, size: { sm: 'h-8 px-3 text-sm', md: 'h-10 px-4 text-base', lg: 'h-12 px-6 text-lg', }, }, defaultVariants: { variant: 'primary', size: 'md', }, } ); ``` ### CSS Modules ```css /* Button.module.css */ .button { display: inline-flex; align-items: center; justify-content: center; border-radius: 0.375rem; font-weight: 500; transition: all 0.2s; } .primary { background-color: var(--color-primary); color: white; } .primary:hover { background-color: var(--color-primary-dark); } ``` ## Accessibility ### ARIA Patterns **Modal Dialog:** ```typescript function Modal({ isOpen, onClose, title, children }) { const modalRef = useRef(null); useEffect(() => { if (isOpen) { modalRef.current?.focus(); } }, [isOpen]); if (!isOpen) return null; return (

e.key === 'Escape' && onClose()} > {children}
); } ``` **Tab Panel:** ```typescript function Tabs({ tabs, activeTab, onChange }) { return (
{tabs.map((tab, index) => ( ))}
{tabs.map((tab, index) => ( ))}
); } ``` ### Accessibility Checklist - [ ] Keyboard navigation works - [ ] Focus indicators visible - [ ] Color contrast meets WCAG AA - [ ] Images have alt text - [ ] Form inputs have labels - [ ] Error messages are announced - [ ] Skip links present - [ ] Heading hierarchy correct - [ ] ARIA labels for icons - [ ] Motion respects user preferences ## Performance Optimization ### Code Splitting ```typescript // Route-based splitting const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); // Component-based splitting const HeavyChart = lazy(() => import('./components/HeavyChart')); // Named exports const { DataTable } = lazy(() => import('./components/DataTable').then((module) => ({ default: module.DataTable, })) ); ``` ### Memoization ```typescript // Memoize expensive component const ExpensiveList = memo(function ExpensiveList({ items, onSelect }) { return (
    {items.map((item) => (
  • onSelect(item.id)}> {item.name}
  • ))}
); }); // Memoize callback function Parent() { const [selected, setSelected] = useState(null); const handleSelect = useCallback((id: string) => { setSelected(id); }, []); return ; } // Memoize computed value function DataDisplay({ data }) { const processedData = useMemo(() => { return data.map(expensiveTransform).filter(expensiveFilter); }, [data]); return ; } ``` ### Virtual Lists ```typescript import { useVirtualizer } from '@tanstack/react-virtual'; function VirtualList({ items }) { const parentRef = useRef(null); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, overscan: 5, }); return (
{virtualizer.getVirtualItems().map((virtualItem) => (
{items[virtualItem.index].name}
))}
); } ``` ## Testing ### Component Testing ```typescript import { render, screen, fireEvent } from '@testing-library/react'; describe('Button', () => { it('renders with correct text', () => { render(); expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument(); }); it('calls onClick when clicked', () => { const onClick = jest.fn(); render(); fireEvent.click(screen.getByRole('button')); expect(onClick).toHaveBeenCalledTimes(1); }); it('is disabled when disabled prop is true', () => { render(); expect(screen.getByRole('button')).toBeDisabled(); }); }); ``` ### Hook Testing ```typescript import { renderHook, act } from '@testing-library/react'; describe('useCounter', () => { it('increments counter', () => { const { result } = renderHook(() => useCounter(0)); act(() => { result.current.increment(); }); expect(result.current.count).toBe(1); }); }); ``` ## Reference Materials - `references/react_patterns.md` - Advanced React patterns - `references/css_architecture.md` - CSS organization - `references/accessibility.md` - A11y guidelines - `references/performance.md` - Performance optimization ## Scripts ```bash # Component scaffolder python scripts/component_gen.py --name Button --type atom # Bundle analyzer python scripts/bundle_analyzer.py --build-dir ./dist # Accessibility audit python scripts/a11y_audit.py --url http://localhost:3000 # Performance report python scripts/perf_report.py --lighthouse-json report.json ```