intermediate 2 min answer

A team asks for a new prop on a shared component. When do you say no, and what do you offer instead?

design-systemapi-surfacecompositioncontractsdiscipline
Show the full answer Hide the answer

What is being tested

Whether you treat a shared component's surface as permanent API rather than as a convenience.

When to say no

When the prop is presentational rather than semantic. color="red" locks the design system out of changing what danger looks like. variant="danger" does not.

When it encodes one consumer's specific case. A prop used by one team is surface area everyone maintains forever.

When it interacts combinatorially. Every option multiplies the states that can occur, and you cannot test them all. A component with thirty props has usually absorbed several distinct components.

When it is asking the component to be a different component. That is the signal to create a second one, not to add a flag.

What to offer instead

Composition. A slot that accepts children beats twenty boolean flags, and it accommodates cases the author never anticipated. This is the answer most of the time.

A second component, sharing internals, for a genuinely different purpose.

Extension points — a render prop, a class hook, a documented styling contract — where the variation is presentational and bounded.

Fork it into their codebase, honestly, where the need is genuinely local. A shared component that serves 90% of cases plus a local variant is healthier than one serving 100% badly.

What a good contract looks like

  • Small, purposeful prop surface.
  • Semantic rather than presentational props.
  • Composition over configuration.
  • Accessibility guaranteed by the component, not left to consumers — keyboard behaviour, focus management, ARIA semantics. If each consumer must get them right, most will not.
  • Controlled and uncontrolled modes stated explicitly, since ambiguity here is a recurring bug source.
  • A documented breaking-change policy, because a shared component has consumers you cannot enumerate.

What the library needs regardless

Semantic versioning with a real policy, deprecation warnings in development builds, visual regression testing (a CSS change can break consumers in ways no unit test catches), and a migration path for breaking changes — ideally a codemod.