--- description: Use after migrating/refactoring features (especially tables/data grids) when reviewing component structure - enforces merging over-split components, colocating files where used, removing unused code, following vertical slice architecture. Prevents premature abstraction and over-engineering. name: component-colocation metadata: skiller: source: .agents/rules/component-colocation.mdc --- # Component Colocation & Refactoring ## Overview React Compiler removes many performance-only reasons to split components where it is enabled, including the canonical `example` app. Merge related code, colocate files where they are used, and delete unused files. Split only for genuine reuse, package boundaries, independent testing, or hook decoupling. ## Kitcn Boundary - Apply this to `example/**`, `www/**`, and package UI modules after checking whether the affected app actually enables React Compiler. - Do not merge across public package exports, runtime entrypoints, generated boundaries, CLI template ownership, or React/Solid framework boundaries. - Scaffolded fixture output is generated. Improve its source template, then regenerate fixtures; never colocate by editing committed fixture output first. ## When to Use - After implementing a new feature (especially tables/data grids) - When reviewing component structure during refactoring - When you notice files spread across multiple folders that are only used in one place - When cleaning up after removing a context/state management migration ## Core Principles ### 1. Don't Over-Split Components **React Compiler handles memoization automatically.** You don't need to split components into smaller pieces for performance. ```tsx // ❌ Over-split: separate files for each button group FormDraftActionButtons.tsx; FormEsignPendingActionButtons.tsx; FormSignedActionButtons.tsx; // ↑ Each file has similar hooks, similar logic, different render // ✅ Single file with all logic colocated ReportHistoryActionButtons.tsx; // ↑ One component, switch/conditional for different states ``` ### 2. Large Files Are Fine Don't fear 300-500 line components. Splitting creates: - More files to navigate - Props drilling between components - Harder-to-follow data flow - Redundant hook calls ### 3. Colocate Where Used **Vertical slice architecture:** Keep feature code together. ``` // ❌ Scattered across shared folders src/components/shared/ActionButtons.tsx src/components/shared/StatusBadge.tsx src/hooks/useReportActions.ts // ✅ Colocated in feature folder src/app/(protected)/report-history/ _components/ report-history-action-buttons.tsx report-history-columns.tsx report-history-table.tsx ``` ### 4. Ask Before Splitting Only split components when: 1. **Hook decoupling**: Component needs different hook contexts 2. **Genuine reuse**: Used in 2+ unrelated features 3. **Explicit request**: User asks for separation **Never split for:** - "Readability" (large files are readable) - "Performance" (React Compiler handles it) - "Single responsibility" (SRP doesn't mean tiny files) ## Post-Feature Checklist After implementing a feature, review: - [ ] **Unused files**: Delete components/hooks no longer referenced - [ ] **Over-split components**: Merge files that are only used together - [ ] **Scattered locations**: Move files to feature's `_components` folder if only used there - [ ] **Prop drilling**: If passing 5+ props between split components, merge them - [ ] **Duplicate hooks**: If multiple components call same hooks, merge components ## Common Mistakes | Pattern | Problem | Fix | | ----------------------------------------- | ----------------------------------- | --------------------------------------------- | | One component per file for "each variant" | 7 files instead of 1 | Merge into single component with conditionals | | Shared folder for feature-specific code | Hard to find, pollutes shared space | Move to feature's `_components` | | Keeping deleted context's components | Dead code, confusion | Delete immediately | | Splitting for "testability" | Tests can test large components | Keep together, test the whole thing | ## Red Flags - Merge Instead - Creating new file for component used in only one place - Passing props through 2+ levels just to reach a split component - Multiple small components with identical hook calls - "Shared" folder containing feature-specific code - Components named `*Part1`, `*Section`, `*Inner` ## Example: Action Buttons Refactor **Before (over-split):** ``` report-history-table/ ActionButtons.tsx # Router wrapper FormDraftActionButtons.tsx # Draft state buttons FormEsignPendingActionButtons.tsx FormISOActionButtons.tsx FormMarkedCompleteActionButtons.tsx FormRefusedActionButtons.tsx FormSignedESignedActionButtons.tsx RefusedButton.tsx # Single button extracted ``` **After (colocated):** ``` _components/ report-history-action-buttons.tsx # All logic in one file ``` Single 400-line file with switch statement for each form status. All hooks called once, no prop drilling, easy to follow.