Children and Slots Beat Booleans
Composition Over Configuration
When a component grows a forest of `showX` booleans, redesign it as a container whose pieces the caller composes.
What you'll learn
- Recognize "configuration soup"
- Refactor toward `children` + slot props
- Compound components — `Card.Header`, `Card.Body`
A component with too many boolean props (showHeader, showClose,
useCompactLayout, …) is hard to read, hard to extend, and tends
to grow forever. The fix: turn it into a container whose internals
the caller composes.
The Smell
<Modal
showClose
showHeader
title="Delete this?"
showCancel
cancelLabel="No"
showOk
okLabel="Yes"
okKind="danger"
/> Every new variant adds another prop. The API balloons.
The Refactor — Compound Components
function Modal({ onClose, children }) {
return (
<div className="modal" role="dialog">
<button onClick={onClose} aria-label="Close">×</button>
{children}
</div>
);
}
Modal.Header = function ModalHeader({ children }) {
return <header>{children}</header>;
};
Modal.Body = function ModalBody({ children }) {
return <div className="modal__body">{children}</div>;
};
Modal.Footer = function ModalFooter({ children }) {
return <footer>{children}</footer>;
}; The caller composes the pieces:
<Modal onClose={close}>
<Modal.Header>Delete this?</Modal.Header>
<Modal.Body>This action can't be undone.</Modal.Body>
<Modal.Footer>
<Button onClick={close}>No</Button>
<Button kind="danger" onClick={confirm}>Yes</Button>
</Modal.Footer>
</Modal> Adding a new section is a new sub-component, not a new prop. Removing one is just deleting JSX.
Slot Props
Sometimes you want named regions, not stacked children:
function Layout({ nav, sidebar, children }) {
return (
<div className="layout">
<header>{nav}</header>
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
<Layout nav={<TopNav />} sidebar={<UserMenu />}>
<Article />
</Layout> nav and sidebar are slot props — they take JSX directly.
When Configuration Is Right
Some props really ARE configuration — a Button with size="md" | "lg" is fine. The smell starts when you have 5+ booleans that
toggle whole regions of the UI. At that point, composition wins.
Up Next
A pattern question that comes up constantly — should this component own its own state, or let the parent control it?
Controlled vs Uncontrolled →