When designing a component and its corresponding API, some key factors should be considered to ensure they are easy to consume, consistent with the rest of the system, and easy to scale and maintain in the future.
a) Which parts can be isolated?
Complex components are hard to consume. To simplify their APIs, it is good practice to isolate smaller, reusable elements.
These elements can be wrapped inside the parent component or manually added by the consumer as child elements, depending on the amount of variation expected (see paragraph d) about slots).
b) Which variations should be offered?
With an overview of all possible use cases, designers can help define which parts of a component should be customisable through the use of properties and which should be kept stable, avoiding unwanted variations and therefore enhancing design consistency.
On the image below,
icon are customisable, while
removable are not designed to be changed.
c) Which styles should be customisable?
Since consumers do not have access to the encapsulated content, customising styles can only be done through APIs.
CSS variables can be used for changing single css values (e.g.
--border-radius). In case multiple styles should be changed together for a given variation (e.g. alert type changing icon color and font size) a property could be used instead.
Variables can be defined as a global theme (e.g.
--accent-color) and modified for a single component, or new variables can be defined only for a given component (e.g.
d) How will the component evolve in the future?
Components and their APIs evolve over time as new use cases arise. For this reason, they should be designed for change, based on facts or forecasts of how use cases may evolve.
An API that is not designed with evolution in mind will likely result in breaking changes when new use cases come up.
On the image below, the warning variation of the dialog could be defined as a
warning boolean prop, but if error or success use cases are expected to come up in the future, it could instead be defined as a
type="warning" string prop.
e) Where can content be inserted?
Not all functionalities of a component need to be pre-defined and offered through specific APIs.
For use cases that require more flexibility, consumers should be able to insert custom content inside pre-defined slots (AKA portals, containers or children areas).
Slots can define how its children elements will appear (e.g. from top to bottom or left to right, with 8px space between them), but the consumers have full control over the style of the inserted elements, since they are not encapsulated.