Compose components from slots
Build UI from small pieces that take children, not a prop per layout.
From frontend-patterns, section “Composition Over Inheritance”.
Build a card nobody planned
Reach both goals on each side. Pick a piece, then a slot.
One Card, 9 propsBad
Card + piecesGood
Every new layout costs a prop
Ship requests. Click one again to take it back.
MonolithBad
4 props +0
interface CardProps {}
ComposedGood
2 props +0
interface CardProps { children: React.ReactNode variant?: 'default' | 'outlined' } // call sites
variant changes one class
Flip the variant, then edit the body text.
RenderedOutput
Invoice #1042
Due Oct 1 · $4,200.00
DOMLive
<div class="card card-default"> <div class="card-header">Invoice #1042</div> <div class="card-body">Due Oct 1 · $4,200.00</div></div>
<Card variant="outlined">
<CardHeader>Invoice #1042</CardHeader>
<CardBody>Due Oct 1 · $4,200.00</CardBody>
</Card>
Why it matters, pros and cons
Why it matters
Card never knows what's inside it. New layouts live at the call site.
Pros
- Unplanned layouts work without touching Card.
- API stays at
childrenandvariant. - Each piece is small and testable alone.
Cons
- Call sites get longer; wrap repeats in a named component.
- Nothing stops an off-spec layout.
- Shared state between pieces needs context.