← Index

Building components that adapt across product needs

Designing components that absorb product variation

At Deezer, Tempo exists without a fully dedicated Design System team, either on the design side or the engineering side. Component work has to fit between product needs, roadmap constraints, and the available capacity of designers and engineers.

This changes the way components are designed from the very beginning.


Problem

Product teams rarely need the exact same component twice. A component created for one feature often becomes relevant elsewhere, but with small differences in layout, content or behaviour.

When those variations have not been considered early enough, each new use case can require another component, a feature-specific variant, or a redesign of the original structure. In a system maintained alongside product work, that repetition quickly increases the number of components, variants, and behaviours the team has to maintain.


Starting from neutral building blocks

This approach also applies below the component level.

Whenever possible, components are assembled from small, shared building blocks that do not carry product-specific semantics. A structural element should not assume that it belongs to Settings, Search, a playlist, or any other particular feature when the same behaviour could be useful elsewhere.

Keeping these foundations semantically neutral makes them easier to combine across different product contexts. Product meaning is introduced through content and configuration rather than being embedded in the underlying structure.

Semantically neutral building blocks can be recombined across product contexts without embedding feature-specific assumptions

This creates a more atomic system: shared elements can be reused to compose larger components, while the same layout, spacing, interaction, and accessibility decisions remain consistent across them.


Designing for likely variation

When a new component is needed, we cannot design only for the immediate use case. We need to anticipate the most likely variations early enough to avoid creating new Design System work every time a product team needs a slightly different version.

This means defining components with flexible properties from the start: with or without icon, leading or centered alignment, with or without action, single button or button group, different content densities, and other common variations.

Components anticipate recurring product variations instead of solving only the first use case
Components anticipate recurring product variations instead of solving only the first use case

The intent is not to predict every possible future request. It is to look beyond the first screen and identify which structural differences are likely to recur.


Building around composition

Slots are an important part of that approach. Some components are built mostly, or entirely, around slots so they can support multiple product contexts without requiring a new component each time.

Interchangeable slots allow one base structure to support multiple product configurations without multiplying components
Interchangeable slots allow one base structure to support multiple product configurations without multiplying components

Item List is a good example. It was initially created for Settings, but its structure also needed to support many variations: a chevron, toggle, radio button, checkbox, icon, metadata, or different trailing actions. By defining the component around interchangeable slots, the same base structure can absorb those variations while keeping a consistent layout and behaviour.


Knowing where to stop

The objective is not to make components infinitely configurable. Too much flexibility makes a system harder to understand, use, test, and maintain.

At Deezer, we managed this by defining preferred configurations based on patterns that were already used or strongly expected across the product. These defaults covered the most common cases and gave teams a clear, predictable path through the component.

The underlying properties remained accessible when a legitimate product need could not be met by those preferred configurations. Teams could adapt the component without immediately creating a new variant, but that flexibility was available to support a concrete need rather than encourage arbitrary customization.

The work was therefore not only to decide what a component could support, but also what it should present by default. The component API could remain broader than the set of configurations actively promoted in the library.


Outcome

This approach helped Tempo remain usable in a context where each new component request could otherwise become maintenance debt.

Components could support a broader range of product situations without multiplying feature-specific variants. Preferred configurations kept everyday use straightforward, while semantically neutral building blocks made the system more predictable to extend, implement, and maintain.