Not everything that looks the same is the same thing.
"Decide when a UI pattern becomes a component and when it stays a one-off."
Why this exists
Premature componentization is as bad as none at all. I have seen codebases with forty-seven button variants because someone abstracted too early. I have also seen projects where every modal was rebuilt from scratch because nobody checked if this was the third time. Both failures cost time and money. This rule gives you a threshold before you reach for either extreme.
Operational Flow
Count occurrences: Before proposing a component, find three distinct places in the project where it already exists or is definitely needed.
Name it precisely: If you can't write a one-sentence description of what the component does without the word 'and', split it.
Audit props early: Document every variant the component must support on day one. Variants discovered later cost twice as much to add.
Check the design system first: Search Figma and the codebase for an existing pattern. If nothing fits in three minutes, it doesn't exist.
Write the usage example first: Sketch how the component will be called in code or placed in Figma. If the interface feels awkward, the component is wrong.
Flag deprecation risk: If you build a component for a single client feature, mark it as project-scoped. Don't migrate it to the shared system without a deliberate review.
What good looks like
- A designer proposes a StatusBadge component and provides a Figma frame showing all four states (success, warning, error, neutral) before writing code.
- An engineer finds a second use case for a component and opens a PR that adds exactly one new prop, documented and typed, instead of copy-pasting the implementation.
- The shared library has under thirty components, and every single one is used in at least two places in production.
What NOT to do
- Don't create a component because the design looks similar. Check whether the underlying behavior and data shape match.
- Don't add props to a component to handle a one-off edge case. Build a wrapper or a separate component instead.
- Don't ship a component without a usage example in Storybook or an isolated view. Undocumented components get misused within a week.
The most expensive component we ever built was a universal card. We designed it to handle eight different content types across three client projects. By the time the fourth project touched it, the component had twenty-two props and a seventeen-line conditional render. Nobody wanted to change it because nobody understood it. It wasn’t bad engineering at the start; it was just an abstraction that grew faster than our reasoning.
You earn component status by appearing three times with the same behavior, not just the same shape. Visual similarity is a clue, not a verdict. When in doubt, copy the code and wait. Duplication is easy to reverse. A bad abstraction is a six-hour refactor waiting for the worst possible week.