shadowsys-memphis

modularize-react-tabs

Safely extract and modularize tabs, sub-views, and large components from monolithic React files with zero regressions.

shadowsys-memphis 1 Updated 4w ago
GitHub

Install

npx skillscat add shadowsys-memphis/brainguardian/modularize-react-tabs

Install via the SkillsCat registry.

SKILL.md

Modularize React Tabs Skill

This skill provides a battle-tested protocol for decomposing monolithic React view files (e.g. admin-view.tsx) into clean, single-responsibility tab components.


The Golden Rules of Modularization

  1. One Component per Pass: Never extract multiple tabs or sections at once. Always isolate, move, wire, verify, and commit one component at a time.
  2. Pure Relocation (Zero Drive-By Refactoring): When moving code, do NOT try to "improve" logic, rename props, or modernize syntax. Move the exact implementation as-is. Refactoring logic comes after modularization, never during.
  3. Pre-Flight and Post-Flight Typecheck: Always run pnpm run typecheck before cutting code and immediately after wiring the new component. If typecheck fails, fix the imports before touching anything else.

The 6-Step Extraction Workflow

Step 1: Pre-Flight Check

Ensure the codebase builds cleanly before starting:

pnpm run typecheck

If errors exist, fix or note them first. Do not refactor on top of a broken build.

Step 2: Identify Component Boundaries & Dependencies

Inspect the tab/section in the monolith:

  • Props & Callbacks: What does the component receive from the parent? (e.g. onNavigate, activeTab, isLocal)
  • Local Types & Constants: Are there category labels, icons, or interface definitions used only by this tab?
  • Shared State / Context: Does it consume hooks (useVault(), useQueryClient(), etc.) directly? (Tabs using React Query hooks are self-contained and easiest to move!)

Step 3: Create the Destination File

Create the new file under a dedicated directory, e.g.:
artifacts/brain-app/src/pages/admin/tabs/<tab-name>-tab.tsx

Structure template:

import React, { useState } from "react";
// 1. UI components (from @/components/ui/...)
// 2. Icons (from lucide-react)
// 3. API hooks / types (from @workspace/api-client-react)
// 4. Context / Utils (from @/lib/...)

interface <TabName>TabProps {
  onNavigate?: (tab: string) => void;
}

export function <TabName>Tab({ onNavigate }: <TabName>TabProps) {
  // Extracted implementation moved here intact
}

Step 4: Wire Component into the Parent Monolith

In the parent file (e.g. admin-view.tsx):

  1. Import the newly created tab:
    import { <TabName>Tab } from "./admin/tabs/<tab-name>-tab";
  2. Replace the inline <TabName>Tab function definition and any exclusively local sub-components/constants with the imported component.
  3. Keep the render switch clean:
    {activeTab === "<tab-name>" && <<TabName>Tab onNavigate={setActiveTab} />}

Step 5: Post-Flight Verification

Run the typecheck to confirm all imported symbols, hooks, and types match:

pnpm run typecheck

Step 6: Prune Dead Parent Imports

Check if the parent monolith now has unused imports (e.g., specific Lucide icons or API hooks that were only used by that extracted tab) and clean them up.