Guidelines for organizing React components in Shadow Master. Use when creating new components, deciding between single-file vs subfolder structure, or understanding the component architecture.
Scanned 2/12/2026
Install via CLI
openskills install majiayu000/claude-skill-registry---
name: component-patterns
description: Guidelines for organizing React components in Shadow Master. Use when creating new components, deciding between single-file vs subfolder structure, or understanding the component architecture.
allowed-tools: Read, Grep, Glob
---
# Component Organization Patterns
Guidelines for structuring React components in the Shadow Master codebase.
## Component Directory Overview
```
/components/ # 130+ components total
├── index.ts # Root exports (DiceRoller only)
├── *.tsx # 6 standalone utility components
├── action-resolution/ # 3 components - dice pool building
├── auth/ # 1 component - email verification
├── character/ # 12 components - character sheet display
├── combat/ # 4 components - combat tracking UI
├── creation/ # 83 components - character creation
│ ├── *.tsx # 14 top-level cards
│ ├── shared/ # 14 reusable utilities
│ └── {feature}/ # 17 feature subfolders
├── cyberlimbs/ # 6 components - augmentation UI
├── sync/ # 2 components - ruleset sync status
└── ui/ # 2 components - BaseModal, Tooltip
```
---
## Decision Flowchart
```
Does the component have modals?
├─ Yes → Create subfolder, extract modals
└─ No → Does it have reusable Row/ListItem components?
├─ Yes, used elsewhere → Create subfolder
└─ No → Keep as single file with internal helpers
```
---
## When to Use a Subfolder
Create a subfolder with `index.ts` when:
- Component has one or more **modals** (selection dialogs, forms, etc.)
- Component has **reusable row/list item** components used in multiple places
- Component exceeds ~600 lines with clear separable concerns
- Component has distinct UI pieces that could be tested independently
**Subfolder structure:**
```
/components/{area}/{feature}/
├── FeatureCard.tsx # Main component
├── FeatureModal.tsx # Selection/edit modal
├── FeatureRow.tsx # Optional: if row is complex/reusable
├── constants.ts # Optional: magic values, options arrays
├── types.ts # Optional: feature-specific types
├── utils.ts # Optional: feature-specific helpers
├── index.ts # Re-exports public API
```
**Index file pattern:**
```typescript
// index.ts - export only public API
export { FeatureCard } from "./FeatureCard";
export { FeatureModal } from "./FeatureModal"; // Only if used externally
```
---
## When to Keep as Single File
Keep as a single file when:
- Component is self-contained with only **internal helper components**
- Internal components are tightly coupled and only make sense within the parent
- Component is under ~400 lines with straightforward structure
- No modals or independently reusable pieces
---
## Component Areas
### Root-Level Components (6 files)
Standalone utility components that don't fit a specific feature area:
| Component | Purpose |
| ---------------------- | ----------------------------------- |
| `DiceRoller.tsx` | Dice rolling UI with edge rerolls |
| `AugmentationCard.tsx` | Generic augmentation display |
| `EssenceDisplay.tsx` | Essence tracking visualization |
| `ThemeProvider.tsx` | Dark/light mode context |
| `EnvironmentBadge.tsx` | Environment indicator (dev/staging) |
| `NotificationBell.tsx` | Notification center UI |
---
### `/components/ui/` - Shared UI Primitives
Low-level accessible components used across the app. Built on React Aria.
| Component | Exports |
| --------------- | ---------------------------------------------------- |
| `BaseModal.tsx` | BaseModal, ModalHeader, ModalBody, ModalFooter |
| `Tooltip.tsx` | Tooltip, TooltipTrigger, TooltipContent, InfoTooltip |
**When to add here:** Generic UI primitives with no business logic.
---
### `/components/auth/` - Authentication Components
| Component | Purpose |
| ----------------------------- | ---------------------------- |
| `EmailVerificationBanner.tsx` | Prompts user to verify email |
---
### `/components/action-resolution/` - Dice Pool Building
Components for building and displaying action resolution dice pools.
| Component | Purpose |
| ----------------------- | -------------------------------- |
| `ActionHistory.tsx` | List of past action rolls |
| `ActionPoolBuilder.tsx` | Construct dice pools for actions |
| `EdgeTracker.tsx` | Edge point tracking and spending |
**Note:** No index.ts - import directly from files.
---
### `/components/character/` - Character Sheet Display
Components for viewing active characters (not creation). No index file - import directly.
| Component | Purpose |
| ------------------------- | --------------------------------- |
| `AdeptPowerList.tsx` | Display adept powers and PP |
| `AutosoftManager.tsx` | Manage vehicle/drone autosofts |
| `CyberdeckConfig.tsx` | Cyberdeck attribute configuration |
| `DroneNetworkManager.tsx` | RCC drone network management |
| `JumpInControl.tsx` | Vehicle/drone jump-in interface |
| `MagicSummary.tsx` | Magic rating, tradition, drain |
| `MatrixActions.tsx` | Matrix action buttons and state |
| `MatrixSummary.tsx` | Matrix attributes and programs |
| `ProgramManager.tsx` | Running programs management |
| `RiggingSummary.tsx` | Rigging stats and VCR mode |
| `Spellbook.tsx` | Spell list with casting interface |
| `VehicleActions.tsx` | Vehicle action buttons |
---
### `/components/combat/` - Combat Tracking
Components for running combat encounters. Has index.ts and co-located tests.
| Component | Purpose |
| ------------------------- | ------------------------------------ |
| `CombatTracker.tsx` | Initiative order and turn management |
| `ActionSelector.tsx` | Action selection with categories |
| `ConditionMonitor.tsx` | Health/damage tracking |
| `OpposedTestResolver.tsx` | Opposed test dice rolling |
---
### `/components/cyberlimbs/` - Cyberlimb Management
Components for cyberlimb augmentation display and modification.
| Component | Purpose |
| ------------------------------- | ----------------------------- |
| `CyberlimbCard.tsx` | Individual cyberlimb display |
| `CyberlimbList.tsx` | List all installed cyberlimbs |
| `CyberlimbDetailPanel.tsx` | Detailed cyberlimb info panel |
| `CyberlimbInstallModal.tsx` | Install new cyberlimb |
| `CyberlimbEnhancementModal.tsx` | Add attribute enhancements |
| `CyberlimbAccessoryModal.tsx` | Add accessories to limb |
---
### `/components/sync/` - Ruleset Synchronization
Components for displaying ruleset sync status and migration.
| Component | Purpose |
| --------------------- | ------------------------------------ |
| `StabilityShield.tsx` | Visual sync status indicator |
| `MigrationWizard.tsx` | Guide user through ruleset migration |
---
### `/components/creation/` - Character Creation
The largest component area (83 components). Organized by feature with shared utilities.
#### Top-Level Cards (14 files)
Single-file cards without complex modals:
| Card | Purpose |
| ----------------------- | ----------------------------- |
| `PrioritySelectionCard` | Priority table selection |
| `AttributesCard` | Attribute allocation |
| `SkillsCard` | Active skills management |
| `SpellsCard` | Spell selection for mages |
| `AdeptPowersCard` | Adept power selection |
| `ComplexFormsCard` | Technomancer complex forms |
| `AugmentationsCard` | Cyberware/bioware selection |
| `VehiclesCard` | Vehicle/drone acquisition |
| `WeaponsPanel` | Weapon purchases |
| `GearTabsCard` | Tabbed gear interface |
| `DerivedStatsCard` | Calculated stats display |
| `CharacterInfoCard` | Name, background, description |
| `EditionSelector` | Edition selection dropdown |
| `CreationErrorBoundary` | Error boundary for creation |
#### Feature Subfolders (17 directories)
| Folder | Components | Pattern |
| ---------------------- | ---------- | --------------------------------------- |
| `/armor` | 4 | Panel + Row + PurchaseModal + ModModal |
| `/augmentations` | 4 | 4 specialized modals |
| `/contacts` | 3 | Card + Modal + KarmaConfirm |
| `/foci` | 2 | Card + Modal |
| `/gear` | 4 | Panel + Row + 2 Modals |
| `/identities` | 6 | Card + Identity + 3 modal types |
| `/knowledge-languages` | 5 | Card + 2 Row types + 2 Modals |
| `/magic-path` | 2 | Card + Modal + utilities |
| `/matrix-gear` | 2 | Card + Modal |
| `/metatype` | 2 | Card + Modal |
| `/qualities` | 3 | Card + SelectionModal + DetailCard |
| `/shared` | 14 | Reusable utilities and hooks |
| `/skills` | 10 | Panel + ListItem + 8 specialized modals |
| `/spells` | 2 | ListItem + Modal |
| `/vehicles` | 4 | 4 specialized modals |
| `/weapons` | 4 | Row + 3 Modals |
#### Shared Utilities (`/creation/shared/`)
| Component | Purpose |
| ------------------------------- | ------------------------------- |
| `CreationCard.tsx` | Standard card wrapper |
| `BudgetIndicator.tsx` | Resource budget display |
| `CardSkeleton.tsx` | Loading skeleton |
| `EmptyState.tsx` | Empty list state |
| `KarmaConversionModal.tsx` | Nuyen ↔ Karma conversion |
| `RatingSelector.tsx` | 1-6 rating picker |
| `Stepper.tsx` | +/- increment control |
| `SummaryFooter.tsx` | Card summary footer |
| `ValidationBadge.tsx` | Validation status indicator |
| `BulkQuantitySelector.tsx` | Quantity picker for bulk items |
| `LifestyleModificationSelector` | Lifestyle mod picker |
| `LifestyleSubscriptionSelector` | Lifestyle subscription picker |
| `useKarmaConversionPrompt.ts` | Hook for karma conversion modal |
---
## Adding Components by Area
### Adding a Creation Card
1. **Determine structure** using the decision flowchart
2. **Create in** `/components/creation/` or `/components/creation/{feature}/`
3. **Use `CreationCard` wrapper** from `/components/creation/shared/`
4. **Add to `SheetCreationLayout.tsx`** in appropriate column
5. **Update `CreationState` type** in `/lib/types/creation.ts` if needed
6. **Export from `/components/creation/index.ts`**
### Adding a Combat Component
1. Create in `/components/combat/`
2. Export from `/components/combat/index.ts`
3. Add co-located test in `/components/combat/__tests__/`
### Adding a Character Sheet Component
1. Create in `/components/character/`
2. Import directly from file (no index.ts)
3. Add to relevant page in `/app/characters/[id]/`
### Adding a Cyberlimb Component
1. Create in `/components/cyberlimbs/`
2. Export from `/components/cyberlimbs/index.ts`
3. Export types if needed for external use
### Adding a UI Primitive
1. Create in `/components/ui/`
2. Build on React Aria for accessibility
3. Export from `/components/ui/index.ts`
4. No business logic - pure presentation
---
## Adding a New API Endpoint
1. Create `/app/api/{path}/route.ts`
2. Export HTTP method handlers (GET, POST, PUT, DELETE)
3. Follow authentication pattern (getSession → validate user)
4. Call storage layer functions
5. Return JSON responses
---
## Adding a New Ruleset Module
1. Define module type in `/lib/types/edition.ts`
2. Add module to book payload in `/data/editions/{editionCode}/`
3. Update merge logic in `/lib/rules/merge.ts` if special handling needed
4. Create hook in `RulesetContext.tsx` for easy access
---
## Key Reference Files
- `components/ui/BaseModal.tsx` - Accessible modal foundation
- `components/creation/shared/CreationCard.tsx` - Card wrapper pattern
- `components/creation/SkillsCard.tsx` - Modal-based editing example
- `components/combat/CombatTracker.tsx` - Combat component with tests
- `components/cyberlimbs/index.ts` - Feature folder export pattern
- `app/characters/create/sheet/components/SheetCreationLayout.tsx` - Three-column layout
---
## Component Diagram Generation
Mermaid diagrams are auto-generated from the component structure.
### Commands
```bash
# Preview all areas to stdout
pnpm generate-diagrams
# Generate specific area
pnpm generate-diagrams --area=combat
pnpm generate-diagrams --area=creation
# Update documentation files
pnpm generate-diagrams --output=files
# Verbose mode with component counts
pnpm generate-diagrams --verbose
```
### Output Locations
| Mode | Location |
| ----------------- | ------------------------------------------ |
| `--output=stdout` | Prints to terminal (default) |
| `--output=files` | Writes to `/docs/architecture/components/` |
### Diagram Color Key
| Color | Hex | Component Type | Naming Pattern |
| ------ | --------- | -------------- | ----------------------------------------- |
| Blue | `#3b82f6` | Container | `*Card.tsx`, `*Panel.tsx`, `*Tracker.tsx` |
| Purple | `#8b5cf6` | Modal | `*Modal.tsx` |
| Green | `#22c55e` | Row | `*Row.tsx`, `*ListItem.tsx` |
| Orange | `#f59e0b` | Hook | `use*.ts`, `*Context.tsx` |
| Gray | `#6b7280` | Shared | Everything else |
### When to Regenerate
Run `pnpm generate-diagrams --output=files` after:
- Adding a new component folder
- Adding/removing modals or cards
- Reorganizing component structure
- Before major documentation updates
### Validation
```bash
# Validate creation docs structure (doesn't regenerate)
pnpm validate-creation-docs --verbose
```
---
## Documentation Structure
### Hand-Written (detailed)
`/docs/architecture/creation-components/` - Detailed creation component docs with:
- Component descriptions
- Props documentation
- Usage patterns
- Context dependencies
### Auto-Generated (overview)
`/docs/architecture/components/` - Generated hierarchy diagrams:
- Mermaid component trees
- Summary tables
- Color-coded by type
---
## Index File Conventions
| Area | Has index.ts? | Reason |
| -------------------- | ------------- | -------------------------------- |
| `/ui` | Yes | Stable public API |
| `/combat` | Yes | Cohesive feature set |
| `/cyberlimbs` | Yes | Cohesive feature set |
| `/sync` | Yes | Cohesive feature set |
| `/creation` | Yes | Organized by phases |
| `/character` | No | Loosely coupled, import directly |
| `/action-resolution` | No | Loosely coupled, import directly |
| `/auth` | No | Single component |
No comments yet. Be the first to comment!