-
Notifications
You must be signed in to change notification settings - Fork 10
Component Builder Pattern
We are building a set of complex, reusable React components such as Forms, Tables, Select, Dropdowns etc, which need to be flexible enough to support both low-level customization and high-level simplicity.
Traditionally, React (and low-level libraries like Radix) encourage component composition to build UI pieces from small, focused units. However, complex components like tables, forms, or wizards often require intricate wiring of multiple subcomponents, props, and state, which can become verbose and error-prone when composing manually.
To balance flexibility and simplicity, we propose a dual-API strategy:
-
Compositional API – Offers granular control for advanced use cases and custom presentation needs.
-
Builder Pattern API – Encapsulates complexity by allowing the consumer to pass configuration via props, enforcing consistency and reducing surface area.
We should aim to support both APIs for our complex components.
Used when consumers require full control over rendering, layout, and component structure. Prefer giving small components, independent of business logic. Allow user to compose them as needed, combining few or all provided components.
Example:
<Table.Root className=''>
<Table.Head className=''>
<Table.Cell className='' />
<Table.Cell />
</Table.Head>
<Table.Row>
<Table.Cell />
<Table.Cell />
</Table.Row>
</Table.Root>
- Encourages clear separation of concerns
- Useful for advanced styling, animations, or nested rendering logic
- Ideal for design systems or when integrating with third-party components
- Allows for customisations via composition
Used for common use cases where simplicity and convention are more valuable than flexibility. Prefer strongly typed props over children. Component can encompass small amounts of business logic to reduce developer toil.
Example:
<Table
data={data}
columns={columns}
/>
- Reduces boilerplate and simplifies API surface
- Enforces consistent styling and behavior
- Easier onboarding for new developers or rapid prototyping
Pros:
- Enables power users to deeply customize components via composition
- Simplifies common use cases via builder-style API
- Encourages adoption by supporting different developer needs
Cons:
- Slightly increases component complexity and maintenance overhead
- Must clearly document when and how to use each API
- Possible API surface duplication
- Design the builder pattern using the same internal primitives as the composition API.
- Ensure both APIs are well-tested and documented.
- Provide visual examples and usage guidelines in Storybook or docs.
- Prefer internal usage of the builder API for consistency, unless specific needs justify composition.