Compound Parts Over a Mega-Component
SHOULD: Expose components as composable compound parts (Parent owns state/context; Parent.Trigger, Parent.Content, Parent.Item are children) rather than one component with a dozen configuration props. New needs become children, not new props and internal branches. Reserve flat single-prop APIs for atomic things with no inside.
Expose a component as composable parts (Select.Trigger / Select.Content) rather than one component with a dozen configuration props
<Select value={v} onChange={setV}>
<SelectTrigger />
<SelectContent><SelectItem value="a">A</SelectItem></SelectContent>
</Select>Bad
Good
Why it matters
A component that starts as `<Select options value onChange>` grows a new prop every time a caller needs something slightly different — a label, an icon, a sticky header, a custom empty state — until it is a maze of props and internal conditionals that no one can safely change. Compound components invert this: the parent owns state and context, and the caller composes the pieces (`<Select><SelectTrigger/><SelectContent><SelectItem/></SelectContent></Select>`).
New requirements become new children, not new props, so the component stays closed for modification but open for extension. This is the pattern shadcn/ui and Radix are built on, and it is why they rarely need a breaking change to support a new layout. Reserve the flat single-prop API for genuinely atomic things (an icon, a badge) that have no inside.