Components as contracts

  • Updated

When you import a component from a design library or a code repository, the components are largely black boxes: you include them and pass in (or set) properties for how they should display. This creates an implicit contract that we need to be conscious of.


What it means to consume a component

Using examples in a React codebase and a component in Figma, the behavior between them is closer than ever. Both allow you to import components from another location – an npm repo or design library – and use them in your work. Before we see the components rendered, we form an agreement between our work (consumer) and the design system (provider). The agreement is something like this:

  • This component will remain available from this location
  • When I use it, the props or component properties will remain the same even if the range of values I can use increases
  • Any additional properties added later on shouldn’t break the current agreement


Working with ‘black boxes’

Working with systems like this places a lot of responsibility on the component provider to give us something that meets our needs and be relied upon. That can take a little while to get used to as there’s only so much of that component we can affect. We set some properties and rely on the components to appear and function as intended.

Honoring this contract in design and development is a significant part of being a design system team. This doesn’t mean that we’d get everything right from the beginning. New capabilities may be needed in the future. 


Changing the contract

Sometimes we need to change the nature of this contract, changing what a property should accept or removing a property altogether. What may’ve originally been a boolean property (true/false) now must accept one from a list of properties (perhaps as an enum or array). Ideally, this should be relatively in sync between design and code when the change is made. 

An example might be a button that uses a property/prop called isPrimary. Setting this to ‘true’ would give us our primary button, and ‘false’ would give us secondary. A new requirement emerges that we now have 3 variants of buttons, primary, secondary, and tertiary. We can manage this change to the contract by flagging the current property as ‘deprecated’ - meaning that it will soon be removed, so use it with caution. A new property could be added, which might be called ‘type,’ and expects it to be one of those variants from the list. Components can start adopting the new property as soon as it’s available, but who is responsible for removing the old one so we can clean up after ourselves? 

I’ve often seen this as a shared responsibility: each designer and developer can change what property they use in their work, but ultimately, the team or collective that looks after the design system needs to ensure all uses of their component have moved over so that the old property can be removed. For reasons like these, having metrics over the usage of components can be really useful. They can give us a sense of the impact of any change we’d like to make, no matter how small.

The redundant property has been removed, and an amended contract is now in place. Change can and should be enabled by our design systems; we just need to be aware of their impact and how we look after what we create.


Why does this matter?

Working as part of a system can be a real mindset change (depending on what you’re used to). Not having complete control of a layout by including library components you shouldn’t alter can initially feel odd - that changes our focus to solving the specific problem we need to solve and means we need to trust and have confidence in the parts we pull from the library. In code, it’s more familiar, but here it’s the alignment with design and not necessarily being able to refactor.

It’s a change to the way of working that can feel uncomfortable, but it’s a useful way of looking at change management and creating a culture that enables change in a joined-up way. It’s not that changes can’t be made - they should be encouraged! With change comes responsibility. These black boxes may change within them, changing your overall composition. Done for the right reasons, that’s a good thing but means that we need to give up a sense of control and feed into a wider process. 

Part of that acceptance is that our personal preferences or taste need to take more of a back seat to things that help the harmony of the overall site or app. Being able to contribute to what’s inside the black boxes and help improve them requires us to focus on communication and collaboration, ensuring that things can be challenged as work progresses for the betterment of the system.

Was this article helpful?