R1.11.3parent-child composition constraintsdesign

Legal parent-child pairings need explicit constraints

Aliases: compound constraints · allowed children · legal nesting

What it is

Trees allow arbitrary nesting by default. Parent and child in a design system are not arbitrary: options belong in a select, column headers in a table, menu items in a menu. Parent-child composition constraints write “who may be whose child” as a rule that can be checked, not as prose someone is expected to remember. Once legal pairings are explicit, illegal nesting is rejected at edit and build time, instead of painting a control that looks right and behaves wrong.

The constraint is on role, not on a class-name string. <Select> accepts <Select.Option>, not a random <div> impersonating an option — even if the div is drawn identically. Looking like an option does not substitute for the contract “I am an option”.

Why it happens

Open composition is the default of a general UI tree: browsers and frameworks let almost any element nest in any other. Design-system components share an internal protocol: selected state bubbles up, arrow keys move among siblings, the current id writes back to the parent. A node without that protocol walking into the tree means the parent cannot read the agreed fields and the child never receives “you are item n”. The picture may still assemble; state and keyboard are already broken.

Spoken rules do not stop copy-paste. Explicit constraints lift the protocol into types, runtime asserts, or an HTML content model: a whitelist of child types on the parent, a required parent context on the child. Checking happens at the moment the call site closes — the place the composition space is actually used. Prose lives outside the call site; the person who reads it and the person who nests wrongly are often not the same.

Where it stops holding

Truly generic layout containers (stack, grid) must accept any child; whitelisting them forbids layout. Third-party widgets embedded across systems cannot join the internal protocol; the constraint should stop at the shell rather than pretend they are legal children. Constraints that are too tight will flag a reasonable extension (custom content inside an option) as illegal; too loose and we are back to “it looks like one”. Choosing among appearance presets is not a parent-child legality problem.

Applying it

  • Publish an allow-table with every compound: parent role, legal child roles, whether multiples are allowed, whether order is meaningful. The table is part of the interface, shipped with the properties.
  • Enforce the table with types or static checks; where static is impossible, throw in development builds on illegal children and name the parent that should have been used.
  • A child used outside a legal parent must fail, not silently paint as an empty shell with no selection and no keyboard.
  • How to check: write two calls — options inside a menu, menu items inside a select. Both must fail in the editor or at build, and the error must name the correct parent. Then write a legal nest: arrow keys and selected state must work end to end. If the only barrier is a sentence saying “don’t do this” and the build still passes, the constraint does not exist.

Related

  • Same group: R1.11.1 Slots return the decision about content to the consumer · R1.11.2 Assembly is less ambiguous than passing props · R1.11.4 Context lets children adapt to the container they sit in
  • Adjacent: R1.02 Component library and variants · R1.06 Contribution and governance
  • Search terms: parent-child composition constraints · compound component · allowed children

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/R1.11.3