Compound Components: One Flexible Family vs Twelve Props Picture a tabs component built the way most people build it first: one component, one giant prop list. , , , , , , ... Every new layout requirement — an icon on one tab, a badge on another, a divider between two of them — adds another prop, and the component's internals become a maze of conditionals trying to arrange all of it correctly. The alternative isn't a bigger prop list. It's breaking the one component into a family of small components that share context implicitly, and letting the caller arrange that family however the layout actually needs — the way HTML's own and do it, not the way a single mega-component with a prop would. The insight: shared context, caller-controlled arrangement A compound component isn't several unrelated components. It's one feature, split into parts that communicate through shared context instead of explicit props — so the parent doesn't need to know how many children exist, and each child doesn't need to receive its state from a prop threaded down manually. The caller places the parts wherever the layout requires; the components coordinate themselves. Nothing here required a array or an prop threaded through three levels. Adding a third tab means adding a — not touching the parent component's prop list at all. In Angular The shared context is Angular's dependency injection. A parent component provides shared state; child components inject it, register themselves, and read from it directly: In React The shared context is, unsurprisingly, React Context — a parent provides it, children consume it directly, without any prop being passed by hand: Both versions share the same shape: a parent holding state, children reading and updating it through shared context rather than an ever-growing prop contract. The framework changes the syntax, not the decision. The Trade-off: Is Splitting Into a Family Actually Worth It? It's fair to be skeptical here. A compound component looks like more files and more ceremony than one component with a prop list. Run the argument both ways before deciding. The pain, concretely Nobody starts with twelve props. The prop-list grows one requirement at a time, and each step looks reasonable in isolation: v1: — clean, three props, done. v2: Design wants an icon on the Billing tab only. You add — a second array that must stay index-aligned with . Get the order wrong and the icon silently lands on the wrong tab. v3: Product wants the Billing tab disabled for free-tier users. You add — a third parallel array, this time by index reference instead of by value, which is even easier to get wrong after a reorder. v4: Someone reorders the tabs for a redesign. Now , , and all have to be reordered together, by hand, with no compiler check that they're still in sync. A missed update doesn't error — it just silently disables or iconifies the wrong tab in production. Nothing in that sequence was a bad decision on its own. The damage is cumulative: by v4, the component's real API is "four arrays that must never drift apart," and nothing in the type system enforces that. Side-by-side Prop-list Compound family --- --- --- Adding an icon to one tab New array, must stay index-aligned with Add the icon directly inside that one Reordering tabs Reorder every parallel array in lockstep, by hand Reorder the JSX — nothing else to touch Risk of silent drift High — arrays can mismatch in length or order with no compile error None — each tab carries its own props, nothing to keep in sync Testing one tab in isolation Must construct the whole parent's prop object Render with the context it needs, alone Upfront setup cost Lower — one component, no context/DI wiring Slightly higher — parent must set up shared context once Adding a genuinely new per-tab feature New prop, new array, new index-alignment rule New attribute or child on — parent untouched The signal to switch The moment you're about to add a second parallel array — alongside — that's the trigger, not a matter of taste. One array (just titles) is not a problem worth solving. Two arrays that must stay index-aligned is the exact shape of bug this pattern exists to eliminate. Start simple If will only ever render plain string titles — no per-tab icons, no per-tab disabled state, no per-tab anything — the one-component, one-array version is genuinely simpler, and building the compound family for it on day one is solving a problem you don't have yet. Ship the simple version. Refactor to a compound family the moment a second parallel array is about to be born. The rule When one component's prop list is really trying to describe an arrangement of several related parts, split it into a family of components sharing implicit context — and let the caller arrange them. A prop list has a vocabulary fixed at write time. A compound component's vocabulary is whatever markup the caller can write.