{
  "schema": "https://ai-atoms.com/schemas/skill-v1.json",
  "type": "skill",
  "id": "skill/cc-skill-frontend-patterns",
  "version": "1.0.0",
  "name": "Cc Skill Frontend Patterns",
  "description": "Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.",
  "system_prompt_fragment": "# Frontend Development Patterns\n\nModern frontend patterns for React, Next.js, and performant user interfaces.\n\n## Component Patterns\n\n### Composition Over Inheritance\n\n```typescript\n// ✅ GOOD: Component composition\ninterface CardProps {\n  children: React.ReactNode\n  variant?: 'default' | 'outlined'\n}\n\nexport function Card({ children, variant = 'default' }: CardProps) {\n  return <div className={`card card-${variant}`}>{children}</div>\n}\n\nexport function CardHeader({ children }: { children: React.ReactNode }) {\n  return <div className=\"card-header\">{children}</div>\n}\n\nexport function CardBody({ children }: { children: React.ReactNode }) {\n  return <div className=\"card-body\">{children}</div>\n}\n\n// Usage\n<Card>\n  <CardHeader>Title</CardHeader>\n  <CardBody>Content</CardBody>\n</Card>\n```\n\n### Compound Components\n\n```typescript\ninterface TabsContextValue {\n  activeTab: string\n  setActiveTab: (tab: string) => void\n}\n\nconst TabsContext = createContext<TabsContextValue | undefined>(undefined)\n\nexport function Tabs({ children, defaultTab }: {\n  children: React.ReactNode\n  defaultTab: string\n}) {\n  const [activeTab, setActiveTab] = useState(defaultTab)\n\n  return (\n    <TabsContext.Provider value={{ activeTab, setActiveTab }}>\n      {children}\n    </TabsContext.Provider>\n  )\n}\n\nexport function TabList({ children }: { children: React.ReactNode }) {\n  return <div className=\"tab-list\">{children}</div>\n}\n\nexport function Tab({ id, children }: { id: string, children: React.ReactNode }) {\n  const context = useContext(TabsContext)\n  if (!context) throw new Error('Tab must be used within Tabs')\n\n  return (\n    <button\n      className={context.activeTab === id ? 'active' : ''}\n      onClick={() => context.setActiveTab(id)}\n    >\n      {children}\n    </button>\n  )\n}\n\n// Usage\n<Tabs defaultTab=\"overview\">\n  <TabList>\n    <Tab id=\"overview\">Overview</Tab>\n    <Tab id=\"details\">Details</Tab>\n  </TabList>\n</Tabs>\n```\n\n### Render Props Pattern\n\n```typescript\ninterface DataLoaderProps<T> {\n  url: string\n  children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode\n}\n\nexport function DataLoader<T>({ url, children }: DataLoaderProps<T>) {\n  const [data, setData] = useState<T | null>(null)\n  const [loading, setLoading] = useState(true)\n  const [error, setError] = useState<Error | null>(null)\n\n  useEffect(() => {\n    fetch(url)\n      .then(res => res.json())\n      .then(setData)\n      .catch(setError)\n      .finally(() => setLoading(false))\n  }, [url])\n\n  return <>{children(data, loading, error)}</>\n}\n\n// Usage\n<DataLoader<Market[]> url=\"/api/markets\">\n  {(markets, loading, error) => {\n    if (loading) return <Spinner />\n    if (error) return <Error error={error} />\n    return <MarketList markets={markets!} />\n  }}\n</DataLoader>\n```\n\n## Custom Hooks Patterns\n\n### State Management Hook\n\n```typescript\nexport function useToggle(initialValue = false): [boolean, () => void] {\n  const [value, setValue] = useState(initialValue)\n\n  const toggle = useCallback(() => {\n    setValue(v => !v)\n  }, [])\n\n  return [value, toggle]\n}\n\n// Usage\nconst [isOpen, toggleOpen] = useToggle()\n```\n\n### Async Data Fetching Hook\n\n```typescript\ninterface UseQueryOptions<T> {\n  onSuccess?: (data: T) => void\n  onError?: (error: Error) => void\n  enabled?: boolean\n}\n\nexport function useQuery<T>(\n  key: string,\n  fetcher: () => Promise<T>,\n  options?: UseQueryOptions<T>\n) {\n  const [data, setData] = useState<T | null>(null)\n  const [error, setError] = useState<Error | null>(null)\n  const [loading, setLoading] = useState(false)\n\n  const refetch = useCallback(async () => {\n    setLoading(true)\n    setError(null)\n\n    try {\n      const result = await fetcher()\n      setData(result)\n      options?.onSuccess?.(result)\n    } catch (err) {\n      const error = err as Error\n      setError(error)\n      options?.onError?.(error)\n    } finally {\n      setLoading(false)\n    }\n  }, [fetcher, options])\n\n  useEffect(() => {\n    if (options?.enabled !== false) {\n      refetch()\n    }\n  }, [key, refetch, options?.enabled])\n\n  return { data, error, loading, refetch }\n}\n\n// Usage\nconst { data: markets, loading, error, refetch } = useQuery(\n  'markets',\n  () => fetch('/api/markets').then(r => r.json()),\n  {\n    onSuccess: data => console.log('Fetched', data.length, 'markets'),\n    onError: err => console.error('Failed:', err)\n  }\n)\n```\n\n### Debounce Hook\n\n```typescript\nexport function useDebounce<T>(value: T, delay: number): T {\n  const [debouncedValue, setDebouncedValue] = useState<T>(value)\n\n  useEffect(() => {\n    const handler = setTimeout(() => {\n      setDebouncedValue(value)\n    }, delay)\n\n    return () => clearTimeout(handler)\n  }, [value, delay])\n\n  return debouncedValue\n}\n\n// Usage\nconst [searchQuery, setSearchQuery] = useState('')\nconst debouncedQuery = useDebounce(searchQuery, 500)\n\nuseEffect(() => {\n  if (debouncedQuery) {\n    performSearch(debouncedQuery)\n  }\n}, [debouncedQuery])\n```\n\n## State Management Patterns\n\n### Context + Reducer Pattern\n\n```typescript\ninterface State {\n  markets: Market[]\n  selectedMarket: Market | null\n  loading: boolean\n}\n\ntype Action =\n  | { type: 'SET_MARKETS'; payload: Market[] }\n  | { type: 'SELECT_MARKET'; payload: Market }\n  | { type: 'SET_LOADING'; payload: boolean }\n\nfunction reducer(state: State, action: Action): State {\n  switch (action.type) {\n    case 'SET_MARKETS':\n      return { ...state, markets: action.payload }\n    case 'SELECT_MARKET':\n      return { ...state, selectedMarket: action.payload }\n    case 'SET_LOADING':\n      return { ...state, loading: action.payload }\n    default:\n      return state\n  }\n}\n\nconst MarketContext = createContext<{\n  state: State\n  dispatch: Dispatch<Action>\n} | undefined>(undefined)\n\nexport function MarketProvider({ children }: { children: React.ReactNode }) {\n  const [state, dispatch] = useReducer(reducer, {\n    markets: [],\n    selectedMarket: null,\n    loading: false\n  })\n\n  return (\n    <MarketContext.Provider value={{ state, dispatch }}>\n      {children}\n    </MarketContext.Provider>\n  )\n}\n\nexport function useMarkets() {\n  const context = useContext(MarketContext)\n  if (!context) throw new Error('useMarkets must be used within MarketProvider')\n  return context\n}\n```\n\n## Performance Optimization\n\n### Memoization\n\n```typescript\n// ✅ useMemo for expensive computations\nconst sortedMarkets = useMemo(() => {\n  return markets.sort((a, b) => b.volume - a.volume)\n}, [markets])\n\n// ✅ useCallback for functions passed to children\nconst handleSearch = useCallback((query: string) => {\n  setSearchQuery(query)\n}, [])\n\n// ✅ React.memo for pure components\nexport const MarketCard = React.memo<MarketCardProps>(({ market }) => {\n  return (\n    <div className=\"market-card\">\n      <h3>{market.name}</h3>\n      <p>{market.description}</p>\n    </div>\n  )\n})\n```\n\n### Code Splitting & Lazy Loading\n\n```typescript\nimport { lazy, Suspense } from 'react'\n\n// ✅ Lazy load heavy components\nconst HeavyChart = lazy(() => import('./HeavyChart'))\nconst ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))\n\nexport function Dashboard() {\n  return (\n    <div>\n      <Suspense fallback={<ChartSkeleton />}>\n        <HeavyChart data={data} />\n      </Suspense>\n\n      <Suspense fallback={null}>\n        <ThreeJsBackground />\n      </Suspense>\n    </div>\n  )\n}\n```\n\n### Virtualization for Long Lists\n\n```typescript\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nexport function VirtualMarketList({ markets }: { markets: Market[] }) {\n  const parentRef = useRef<HTMLDivElement>(null)\n\n  const virtualizer = useVirtualizer({\n    count: markets.length,\n    getScrollElement: () => parentRef.current,\n    estimateSize: () => 100,  // Estimated row height\n    overscan: 5  // Extra items to render\n  })\n\n  return (\n    <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>\n      <div\n        style={{\n          height: `${virtualizer.getTotalSize()}px`,\n          position: 'relative'\n        }}\n      >\n        {virtualizer.getVirtualItems().map(virtualRow => (\n          <div\n            key={virtualRow.index}\n            style={{\n              position: 'absolute',\n              top: 0,\n              left: 0,\n              width: '100%',\n              height: `${virtualRow.size}px`,\n              transform: `translateY(${virtualRow.start}px)`\n            }}\n          >\n            <MarketCard market={markets[virtualRow.index]} />\n          </div>\n        ))}\n      </div>\n    </div>\n  )\n}\n```\n\n## Form Handling Patterns\n\n### Controlled Form with Validation\n\n```typescript\ninterface FormData {\n  name: string\n  description: string\n  endDate: string\n}\n\ninterface FormErrors {\n  name?: string\n  description?: string\n  endDate?: string\n}\n\nexport function CreateMarketForm() {\n  const [formData, setFormData] = useState<FormData>({\n    name: '',\n    description: '',\n    endDate: ''\n  })\n\n  const [errors, setErrors] = useState<FormErrors>({})\n\n  const validate = (): boolean => {\n    const newErrors: FormErrors = {}\n\n    if (!formData.name.trim()) {\n      newErrors.name = 'Name is required'\n    } else if (formData.name.length > 200) {\n      newErrors.name = 'Name must be under 200 characters'\n    }\n\n    if (!formData.description.trim()) {\n      newErrors.description = 'Description is required'\n    }\n\n    if (!formData.endDate) {\n      newErrors.endDate = 'End date is required'\n    }\n\n    setErrors(newErrors)\n    return Object.keys(newErrors).length === 0\n  }\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault()\n\n    if (!validate()) return\n\n    try {\n      await createMarket(formData)\n      // Success handling\n    } catch (error) {\n      // Error handling\n    }\n  }\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input\n        value={formData.name}\n        onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}\n        placeholder=\"Market name\"\n      />\n      {errors.name && <span className=\"error\">{errors.name}</span>}\n\n      {/* Other fields */}\n\n      <button type=\"submit\">Create Market</button>\n    </form>\n  )\n}\n```\n\n## Error Boundary Pattern\n\n```typescript\ninterface ErrorBoundaryState {\n  hasError: boolean\n  error: Error | null\n}\n\nexport class ErrorBoundary extends React.Component<\n  { children: React.ReactNode },\n  ErrorBoundaryState\n> {\n  state: ErrorBoundaryState = {\n    hasError: false,\n    error: null\n  }\n\n  static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n    return { hasError: true, error }\n  }\n\n  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n    console.error('Error boundary caught:', error, errorInfo)\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return (\n        <div className=\"error-fallback\">\n          <h2>Something went wrong</h2>\n          <p>{this.state.error?.message}</p>\n          <button onClick={() => this.setState({ hasError: false })}>\n            Try again\n          </button>\n        </div>\n      )\n    }\n\n    return this.props.children\n  }\n}\n\n// Usage\n<ErrorBoundary>\n  <App />\n</ErrorBoundary>\n```\n\n## Animation Patterns\n\n### Framer Motion Animations\n\n```typescript\nimport { motion, AnimatePresence } from 'framer-motion'\n\n// ✅ List animations\nexport function AnimatedMarketList({ markets }: { markets: Market[] }) {\n  return (\n    <AnimatePresence>\n      {markets.map(market => (\n        <motion.div\n          key={market.id}\n          initial={{ opacity: 0, y: 20 }}\n          animate={{ opacity: 1, y: 0 }}\n          exit={{ opacity: 0, y: -20 }}\n          transition={{ duration: 0.3 }}\n        >\n          <MarketCard market={market} />\n        </motion.div>\n      ))}\n    </AnimatePresence>\n  )\n}\n\n// ✅ Modal animations\nexport function Modal({ isOpen, onClose, children }: ModalProps) {\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <>\n          <motion.div\n            className=\"modal-overlay\"\n            initial={{ opacity: 0 }}\n            animate={{ opacity: 1 }}\n            exit={{ opacity: 0 }}\n            onClick={onClose}\n          />\n          <motion.div\n            className=\"modal-content\"\n            initial={{ opacity: 0, scale: 0.9, y: 20 }}\n            animate={{ opacity: 1, scale: 1, y: 0 }}\n            exit={{ opacity: 0, scale: 0.9, y: 20 }}\n          >\n            {children}\n          </motion.div>\n        </>\n      )}\n    </AnimatePresence>\n  )\n}\n```\n\n## Accessibility Patterns\n\n### Keyboard Navigation\n\n```typescript\nexport function Dropdown({ options, onSelect }: DropdownProps) {\n  const [isOpen, setIsOpen] = useState(false)\n  const [activeIndex, setActiveIndex] = useState(0)\n\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    switch (e.key) {\n      case 'ArrowDown':\n        e.preventDefault()\n        setActiveIndex(i => Math.min(i + 1, options.length - 1))\n        break\n      case 'ArrowUp':\n        e.preventDefault()\n        setActiveIndex(i => Math.max(i - 1, 0))\n        break\n      case 'Enter':\n        e.preventDefault()\n        onSelect(options[activeIndex])\n        setIsOpen(false)\n        break\n      case 'Escape':\n        setIsOpen(false)\n        break\n    }\n  }\n\n  return (\n    <div\n      role=\"combobox\"\n      aria-expanded={isOpen}\n      aria-haspopup=\"listbox\"\n      onKeyDown={handleKeyDown}\n    >\n      {/* Dropdown implementation */}\n    </div>\n  )\n}\n```\n\n### Focus Management\n\n```typescript\nexport function Modal({ isOpen, onClose, children }: ModalProps) {\n  const modalRef = useRef<HTMLDivElement>(null)\n  const previousFocusRef = useRef<HTMLElement | null>(null)\n\n  useEffect(() => {\n    if (isOpen) {\n      // Save currently focused element\n      previousFocusRef.current = document.activeElement as HTMLElement\n\n      // Focus modal\n      modalRef.current?.focus()\n    } else {\n      // Restore focus when closing\n      previousFocusRef.current?.focus()\n    }\n  }, [isOpen])\n\n  return isOpen ? (\n    <div\n      ref={modalRef}\n      role=\"dialog\"\n      aria-modal=\"true\"\n      tabIndex={-1}\n      onKeyDown={e => e.key === 'Escape' && onClose()}\n    >\n      {children}\n    </div>\n  ) : null\n}\n```\n\n**Remember**: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.",
  "applicable_domains": [
    "frontend"
  ],
  "category": "frontend",
  "invocation": [
    "/cc-skill-frontend-patterns"
  ],
  "authored_by": "affaan-m",
  "source_url": "https://claudeskills.in/skill/cc-skill-frontend-patterns",
  "provenance": {
    "source": "claudeskills.in",
    "source_url": "https://claudeskills.in/skill/cc-skill-frontend-patterns",
    "author": "affaan-m",
    "license": "unknown",
    "imported_at": "2026-09-03",
    "notes": "Aggregated by claudeskills.in from community GitHub lists."
  },
  "tags": [
    "claudeskills",
    "frontend"
  ],
  "lifecycle": "draft"
}