| name | component-design-patterns |
| description | Component design: Atomic design, composition, prop design, state placement. |
| triggers | {"extensions":[".tsx",".jsx"],"directories":["components/","ui/"],"keywords":["component","props","composition","compound","atomic","slot"]} |
| auto_load_when | Designing or editing React components |
| agent | frontend-ops |
| tools | ["Read","Write","Bash"] |
Component Design Patterns
Focus: Design principles, composition, reusability
1. Component Size Decision
When to split components:
├── Component does too much
│ └── Multiple responsibilities
│ └── Hard to test
│ └── Can describe in one sentence?
│
├── Component is reused in multiple places
│ └── But with different content
│ └── Props control everything
│ └── Use children/slots instead
│
├── Component renders different states
│ └── Loading, error, empty, data
│ └── Extract each to separate component
│
└── Component is hard to maintain
└── 200+ lines
└── Multiple concerns
└── Several reasons to change
When NOT to split:
├── Components are tightly coupled
│ └── Always used together
│ └── Split would make harder
│
├── Premature abstraction
│ └── Not used anywhere else yet
│ └── Wait until second use
│
└── Simplicity is priority
└── Over-abstraction = complexity
└── Trade-off: balance needed
2. Props Design
Props principles:
├── Explicit over implicit
└── Name clearly indicates purpose
└── Avoid: data, value, params
│
├── Prefer objects over primitives
└── Related props together
└── Easier to extend
│
├── Boolean props
└── Use sparingly
└── Better: explicit prop for state
└── Example: isLoading vs loadingState
│
└── Callbacks: verb prefix
└── onClick, onSubmit, onLogin
└── Past tense for handlers: onDataFetched
When to use children:
├── Content is component's responsibility
└── Button with icon + text
└── Card with header/body/footer
│
├── Content varies from caller
└── Not predictable props
└── Use slots for flexibility
│
└── When NOT to use children:
└── Simple data display
└── Predictable content
└── Props more explicit
3. Component Composition
How to compose:
├── Wrapper components
└── Layout: margin, padding, max-width
└── Applies container rules
└── Children are content
│
├── Slot components
└── Card with header/body/footer slots
└── Optional sections
└── Caller controls what's where
│
└── Higher-order components (use carefully)
└── Add behavior (loading, error)
└── Compose multiple behaviors
└── Hooks often better alternative
Composition vs inheritance:
├── Composition preferred
└── Flexible, interchangeable
└── Props control behavior
└── Easy to test
│
└── Inheritance:
└── Avoid for UI components
└── Tight coupling
└── Hard to override
└── Use composition instead
4. Atomic Design Levels
When to use each level:
├── Atoms (basic elements)
└── Button, Input, Label
└── Smallest reusable units
└── No dependencies on other components
│
├── Molecules (simple groups)
└── FormField (Label + Input)
&& SearchBar (Input + Button)
&& Consistent units working together
│
├── Organisms (complex UI)
&& Header, Sidebar, ProductCard
&& Distinct section of UI
&& Multiple molecules/atoms
│
├── Templates (page structure)
&& Layout, ArticleTemplate
&& Blueprint for pages
&& Placeholders for content
│
└── Pages (full templates)
&& HomePage, ProductPage
&& Instantiated templates
&& Connect to data, state
5. State Placement
Where to put state:
├── Component-local state
└── useState for UI state
└── Only used in this component
└── Not passed elsewhere
│
├── Shared state (lift up)
└── Used by multiple children
└── Closest common ancestor
└── Pass down via props or context
│
├── Global state
└── Many components need access
&& User session, theme
&& Use: Zustand, Context
│
└── Server state
&& API data
&& Use: React Query, SWR
&& NOT component state
Key Patterns
- Split when reused - Not before
- Props explicit - Avoid too generic names
- Children for content slots - Props for configuration
- Composition over inheritance - Flexibility
- State in lowest common ancestor - But not lower than needed
Anti-Patterns
❌ Component that does data fetching + rendering + state management
✅ Single responsibility: container (data) vs presentational (UI)
❌ Props drilling 5 levels deep
✅ Composition pattern or context for cross-cutting concerns
❌ Boolean prop explosion (isLoading, isDisabled, isError, isLarge...)
✅ Variant prop with discriminated union: variant="loading" | "error"
❌ Ref forwarding broken by wrapping in HOC
✅ forwardRef at every wrapper; compose with mergeRefs
❌ Component accepting 20+ props
✅ Split component; use render props or compound components for complexity
Quick Reference
| Pattern | Use case | Trade-off |
|---|
| Compound components | Complex related UI | Flexible but verbose API |
| Render props | Injecting behavior | More flexible than HOC |
| HOC | Cross-cutting (auth, analytics) | Hard to compose |
| Custom hook | Reusable logic only | No rendering |
Polymorphic as prop | Semantic element flex | Type complexity |
| Slot pattern | Content projection | Like Vue slots in React |
🌍 Universal Language Support
- Turkish Native: This skill natively supports Turkish. If the user prompt is in Turkish, all analysis, formatting, and output MUST be entirely in Turkish. You do not need explicit "write in Turkish" instructions.