--- name: split-react-components description: Split React/TSX files containing multiple inlined components into separate single-responsibility files. Use when asked to "split components", "extract components", "single responsibility", "clean up component file", "too many components in one file", "component slop", or when running deslop/cleanup on React code. disable-model-invocation: true --- # Split React Components One file, one component, its own types, its own hooks. Anything else is slop. ## What counts as slop 1. **Inline sub-components** defined inside another component's function body. These re-create on every render and bloat the host file. Even if they're small. 2. **SVG icon components** inlined alongside the component that uses them. These belong in a dedicated icons file. 3. **Large string literals / data constants** (SVG markup, config arrays, static data) taking more than ~5 lines. 4. **Interfaces/types** that only exist to serve an extracted component — they travel with it. 5. **Hooks** that serve a single sub-component — extract alongside it. ### Do NOT split - Tiny styled wrappers (< 5 lines) tightly coupled to the parent's markup. - Next.js app router files in `apps/docs` only (`loading.tsx`, `error.tsx`, `layout.tsx`). - Test files. ## Workflow 1. **Scan** — Read the target file(s). List every component definition (named functions, arrow components, `forwardRef` wrappers). 2. **Classify** — Primary export vs. inlined sub-component/helper. 3. **Plan** — For each extraction: - Destination path (follow project conventions — kebab-case filenames, named exports). - Which imports, types, constants move with it. - What the parent needs to import after extraction. 4. **Execute** — Create new files, remove inlined definitions, add imports in parent. 5. **Verify** — No circular imports. Run lints on all modified files. ## File naming - Match project conventions: kebab-case filenames, named exports (`export const ComponentName`). - Icon components → sibling `icons.tsx` or `icons/` subfolder. - Data constants → sibling file named after the constant (e.g. `logo-svg.ts`). - Types → co-locate with the component that owns them. ## Example **Before** — `logo-dropdown.tsx` (167 lines, 5 components in one file): ```tsx import { FC, useState } from 'react'; interface DropdownItem { /* ... */ } interface DropdownSection { /* ... */ } export const LogoDropdown: FC = () => { const logoSvg = ``; const GitHubIcon: FC<{ className?: string }> = ({ className }) => ( ); const LinkedInIcon: FC<{ className?: string }> = ({ className }) => (...); const TwitterIcon: FC<{ className?: string }> = ({ className }) => (...); const StackOverflowIcon: FC<{ className?: string }> = ({ className }) => (...); const sections = [/* uses all icons above */]; return