Skip to main content

Search rules

Search all UI Guides rules by name, category, or source

designComposition Patterns

Compound Parts Over a Mega-Component

SHOULD

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.

Built by Gleb Stroganov, design engineer at Evil Martians.

The rules come from other people's skills and guidelines — Vercel, Rauno Freiberg, @Ibelick, impeccable, Emil Kowalski, Tailwind, RAMS — each one credited on the Sources page. The work here is extraction and wiring: every rule is pulled into one corpus, given a good and a bad example you can operate, a MUST/SHOULD/NEVER rule an agent can paste, and a link back to where it came from.