{"id":"672a2163-f00f-4877-acc6-dd2f01130b36","shortId":"sp5eAJ","kind":"skill","title":"cc-skill-frontend-patterns","tagline":"Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.","description":"# 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.\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["skill","frontend","patterns","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding"],"capabilities":["skill","source-sickn33","skill-cc-skill-frontend-patterns","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/cc-skill-frontend-patterns","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34882 github stars · SKILL.md body (14,555 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T12:50:44.147Z","embedding":null,"createdAt":"2026-04-18T21:34:05.637Z","updatedAt":"2026-04-24T12:50:44.147Z","lastSeenAt":"2026-04-24T12:50:44.147Z","tsv":"'-1':1143 '-20':949 '/api/markets':230,385 '/heavychart':624 '/threejsbackground':629 '0':705,707,801,937,944,947,974,980,990,1001,1004,1030,1056 '0.3':952 '0.9':992,1006 '1':942,977,997,999,1044,1046,1055 '100':669,709 '20':939,994,1008 '200':774,780 '5':674 '500':439 '600px':685 'a.volume':579 'absolut':703 'access':1010 'action':463,483,484,1179 'action.payload':494,501,508 'action.type':487 'activ':156 'activeindex':1027,1063 'activetab':87,109,116 'anim':908,912,922,940,957,975,995 'animatedmarketlist':925 'animatepres':916 'applic':1173 'aria':1077,1081,1139 'aria-expand':1076 'aria-haspopup':1080 'aria-mod':1138 'arrowdown':1038 'arrowup':1049 'ask':1217 'async':280,328,804 'auto':687 'await':336,812 'b':577 'b.volume':578 'best':18 'boolean':177,259,296,461,478,761,851 'boundari':845,885,1225 'break':1047,1057,1066,1071 'button':152,898 'card':51,59,60 'cardbodi':73 'cardhead':65 'cardprop':43,55 'case':488,495,502,1037,1048,1058,1067 'catch':215,343,817 'caught':886 'cc':2 'cc-skill-frontend-pattern':1 'charact':781 'children':44,52,62,66,67,70,74,75,78,102,104,118,122,123,126,131,134,160,172,186,222,524,525,542,586,860,963,1009,1096,1149 'choos':1160 'clarif':1219 'class':856 'classnam':58,153,968,984 'clear':1192 'cleartimeout':424 'close':1127 'code':606 'combobox':1075 'complex':1166 'compon':33,40,83,597,619 'componentdidcatch':878 'composit':35,41 'compound':82 'comput':570 'console.error':397,883 'console.log':391 'const':93,108,136,188,195,200,261,266,276,306,313,320,325,334,345,376,411,417,431,435,512,527,546,571,587,599,620,625,657,661,748,755,759,762,802,1021,1026,1031,1098,1102 'content':81,987 'context':137,141,449,547,551,562 'context.activetab':154 'context.setactivetab':158 'control':724 'count':664 'creat':842 'createcontext':95,514 'createmarket':813 'createmarketform':747 'criteria':1228 'current':1112 'custom':247 'dashboard':632 'data':173,189,223,281,288,307,371,377,390,637,638 'data.length':393 'dataload':184,227 'dataloaderprop':169,187 'date':792 'debounc':400 'debouncedqueri':436,442,444,445 'debouncedvalu':412,429 'default':47,54,509 'defaulttab':103,106,112 'delay':408,422,427 'describ':1180,1196 'descript':733,741,753,785 'detail':163 'develop':7,21 'dialog':1137 'dispatch':517,518,529,541 'div':57,680,688,698,1073,1133 'document.activeelement':1116 'dropdown':1017,1086 'dropdownprop':1020 'durat':951 'e':805,829,1033,1145 'e.key':1036,1146 'e.preventdefault':807,1039,1050,1060 'e.target.value':834 'element':1114 'els':771,1123 'enabl':295,363,369,1155 'end':791 'enddat':735,743,754 'enter':1059 'environ':1208 'environment-specif':1207 'err':344,347,396,399 'error':144,178,179,201,204,225,233,238,240,241,242,292,293,314,317,346,349,351,354,372,380,554,756,818,819,844,852,853,867,871,872,877,879,880,884,887 'errorboundari':857 'errorboundaryst':849,862,864,873 'errorinfo':881,888 'errors.name':838,839 'escap':1068,1147 'estim':670 'estimates':668 'execut':1175 'exit':945,978,1002 'expand':1078 'expens':569 'expert':1213 'export':49,63,71,99,119,127,182,254,297,403,521,543,598,630,651,745,855,923,958,1015,1091 'extend':858 'extra':675 'fail':398 'fallback':635,640 'fals':219,258,324,357,364,536,866,902,1025,1065,1070 'fetch':208,282,384,392 'fetcher':302,337,358 'field':841 'final':217,355 'fit':1163 'focus':1088,1113,1119,1122,1125,1129 'form':721,725,822 'formdata':730,749,814 'formdata.description.trim':783 'formdata.enddate':789 'formdata.name':827 'formdata.name.length':773 'formdata.name.trim':766 'formerror':738,764 'framer':910,919 'framer-mot':918 'frontend':4,6,20,24,1153 'function':50,64,72,100,120,128,183,255,298,404,479,522,544,583,631,652,746,924,959,1016,1092 'getderivedstatefromerror':870 'getscrollel':666 'good':39 'handl':722,816,820 'handlekeydown':1032,1085 'handler':418,425 'handlesearch':588 'handlesubmit':803,824 'haserror':850,865,875,901 'haspopup':1082 'heavi':618 'heavychart':621,636 'height':672,684,690,710 'hook':248,252,283,401 'htmlelement':1105,1118 'id':130,132,155,159 'implement':1087 'import':611,623,628,647,914 'inherit':37 'initi':935,972,988 'initialvalu':257,265 'input':825,1222 'interfac':32,42,85,168,285,453,729,737,848,1159 'isopen':277,961,966,1022,1079,1094,1110,1130,1132 'item':676 'key':300,366,699,933 'keyboard':1012 'lazi':608,612,616,622,627 'left':706 'length':800 'limit':1184 'list':645,921 'listbox':1083 'load':176,196,224,232,235,321,373,379,460,476,504,507,535,609,617 'long':644 'maintain':1156 'manag':13,251,447,1089 'map':696 'market':228,231,245,246,378,383,394,455,456,458,466,468,471,473,490,493,497,532,580,602,654,655,656,718,719,836,843,926,927,928,931,954,955 'market.description':605 'market.id':934 'market.name':604 'marketcard':600,717,953 'marketcontext':513,549 'marketcontext.provider':538 'marketlist':244 'marketprovid':523,560 'markets.length':665 'markets.map':930 'markets.sort':575 'match':1193 'math.max':1053 'math.min':1042 'memoiz':565 'messag':897 'miss':1230 'modal':956,960,970,986,1093,1120,1140 'modal-cont':985 'modal-overlay':969 'modalprop':964,1097 'modalref':1099,1135 'modalref.current':1121 'modern':23,1152 'motion':911,915,920 'motion.div':932,967,983 'must':146,556,777 'name':731,739,752,768,776,833,837 'navig':1013 'new':143,553 'newerror':763,796,799 'newerrors.description':784 'newerrors.enddate':790 'newerrors.name':767,775 'next.js':11,28 'null':175,180,193,194,205,206,311,312,318,319,332,459,534,641,660,854,868,1101,1106,1107,1150 'number':409 'object.keys':798 'onchang':828 'onclick':157,899,981 'onclos':962,982,1095,1148 'onerror':291,353,395 'onkeydown':1084,1144 'onselect':1019,1061 'onsubmit':823 'onsuccess':287,341,389 'opac':936,941,946,973,976,979,989,996,1003 'optim':15,564 'option':304,340,352,359,362,368,1018,1062 'options.length':1045 'outlin':48 'output':1202 'overflow':686 'overlay':971 'overscan':673 'overview':162,1183 'parentref':658,682 'parentref.current':667 'pass':584 'pattern':5,8,22,25,34,166,249,448,451,723,846,909,1011,1154,1161 'payload':467,472,477 'perform':14,30,563,1157 'performsearch':443 'permiss':1223 'placehold':835 'posit':693,702 'practic':19 'prev':831,832 'previousfocusref':1103 'previousfocusref.current':1115,1128 'project':1165 'promis':303 'prop':165 'pure':596 'px':692,712,716 'queri':590,593 'r':387 'r.json':388 'react':10,27,615 'react.component':859 'react.errorinfo':882 'react.formevent':806 'react.keyboardevent':1034 'react.memo':594,601 'react.reactnode':45,68,76,105,124,135,181,526,861 'reduc':450,480,531 'ref':681,1134 'refetch':326,365,367,374,381 'relat':694 'rememb':1151 'render':164,678,889 'requir':770,787,794,1221 'res':211 'res.json':212 'restor':1124 'result':335,339,342 'return':56,69,77,113,125,151,221,236,239,243,272,370,423,428,491,498,505,510,537,561,574,603,633,679,797,810,821,874,892,905,929,965,1072,1131 'review':1214 'role':1074,1136 'row':671 'safeti':1224 'save':1111 'scale':991,998,1005 'scope':1195 'searchqueri':432,438 'select':470,496 'selectedmarket':457,500,533 'set':465,475,489,503 'setactiveindex':1028,1040,1051 'setactivetab':89,110,117 'setdata':190,214,308,338 'setdebouncedvalu':413,420 'seterror':202,216,315,331,350,757,795 'setformdata':750,830 'setisopen':1023,1064,1069 'setload':197,218,322,329,356 'setsearchqueri':433,592 'settimeout':419 'setvalu':263,269 'skill':3,1171,1187 'skill-cc-skill-frontend-patterns' 'someth':893 'sortedmarket':572 'source-sickn33' 'specif':1209 'split':607 'state':12,250,446,454,481,482,485,492,499,506,511,515,516,528,540,863 'static':869 'stop':1215 'string':88,91,107,133,171,301,591,732,734,736,740,742,744 'style':683,689,701 'substitut':1205 'success':815,1227 'suspens':613,634,639 'switch':486,1035 'tab':90,101,129,145,150 'tabindex':1142 'tablist':121 'tabscontext':94,139 'tabscontext.provider':114 'tabscontextvalu':86,96 'tanstack/react-virtual':650 'task':1191 'test':1211 'this.props.children':906 'this.setstate':900 'this.state.error':896 'this.state.haserror':891 'threejsbackground':626 'throw':142,552 'titl':80 'toggl':267,274 'toggleopen':278 'top':704 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'transform':713 'transit':950 'translatey':714 'treat':1200 'tri':333,811,903 'true':199,330,876,1141 'type':462,464,469,474 'typescript':38,84,167,253,284,402,452,566,610,646,728,847,913,1014,1090 'ui':17 'undefin':97,98,519,520 'url':170,185,209,220,229 'usag':79,161,226,275,375,430,907 'use':148,558,1169,1185 'usecallback':268,327,581,589 'usecontext':138,548 'usedebounc':405,437 'useeffect':207,360,416,440,1108 'usemarket':545,555 'usememo':567,573 'usequeri':299,382 'usequeryopt':286,305 'user':31,1158 'usereduc':530 'useref':659,1100,1104 'usest':111,191,198,203,264,309,316,323,414,434,751,758,1024,1029 'usetoggl':256,279 'usevirtu':648,663 'v':270,271 'valid':727,760,809,1210 'valu':115,262,273,406,415,421,426,539,826 'variant':46,53,61 'virtual':642,662 'virtualizer.gettotalsize':691 'virtualizer.getvirtualitems':695 'virtualmarketlist':653 'virtualrow':697 'virtualrow.index':700,720 'virtualrow.size':711 'virtualrow.start':715 'void':92,260,290,294 'went':894 'width':708 'within':149,559 'workflow':1177 'wrong':895 'y':938,943,948,993,1000,1007","prices":[{"id":"5e45edd3-8a77-4db2-b5ce-68846f9f7527","listingId":"672a2163-f00f-4877-acc6-dd2f01130b36","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:34:05.637Z"}],"sources":[{"listingId":"672a2163-f00f-4877-acc6-dd2f01130b36","source":"github","sourceId":"sickn33/antigravity-awesome-skills/cc-skill-frontend-patterns","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/cc-skill-frontend-patterns","isPrimary":false,"firstSeenAt":"2026-04-18T21:34:05.637Z","lastSeenAt":"2026-04-24T12:50:44.147Z"}],"details":{"listingId":"672a2163-f00f-4877-acc6-dd2f01130b36","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"cc-skill-frontend-patterns","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34882,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-24T06:41:17Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"3a40f074713c3507794a12a6eb49fb79e5956651","skill_md_path":"skills/cc-skill-frontend-patterns/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/cc-skill-frontend-patterns"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"cc-skill-frontend-patterns","description":"Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/cc-skill-frontend-patterns"},"updatedAt":"2026-04-24T12:50:44.147Z"}}