The predictability problem

One of the main benefits of using a predefined component is that it has a predefined style and behavior. This makes the component predictable and much less prone to bugs. As long the component is only modified with the given API props, it will keep its promised style and behavior.

Importing a component and applying custom styles, by style property or class, can break the component's predictability.

An example case

Let's say we import a Button component from the library and apply a width style to it. In the future if we add a width to the Button in the library it will conflict with the styles we applied in the app.

<Button className="customStylesInMyApp">Button</Button>
.buttonFromLibrary {
width: 100%;
/* ... */
}
.customStylesInMyApp {
width: 10rem;
}

These styles now are in conflict and hard to track or detect visual bugs.

Sharing code with other developers

As a result, we have a component that is receiving styles from 2 sources: the library and the custom styles. This makes it much harder for other developers to understand how the result is produced. They would need to first understand how the library component works and how the custom style overrides it.

Locking down iteration

Shared components and styles keep the interface consistent and iterative. For example, we can modify the button style and it will propagate through the product, but buttons that are modified with custom styles can fall out of sync and even break.

Solutions

There are many cases where components are too constrained and can't cover all of the special cases. This is natural, components are not meant to solve all problems, but the most common ones.

Wraping the component

In many cases, we need a specific positioning for a component. We can use a wrapper that takes care of the positioning problem. This way the component doesn't need to care where it is.

For example, if we need to position an IconButton in a corner:

This solution is using Lens CSS utilities, but we can also achieve the same by applying a custom class to the wrapper div and use Lens CSS variables.

Building a custom element

We want to use Lens as much as possible, but there are few very good reasons to not use Lens.

  • When building a complex layout. Layouts are one of the most common parts of the interface and each layout has slightly different needs. In many cases we need granular control on a very low level and CSS does exactly that. Combine the custom CSS with Lens CSS variables for consistent spacing.

  • When building an experiment or a temporal feature. If we are not sure that what we are building is going to be a pattern used across the product, it's much better to build it as a custom element.

Feedback to Lens

It's more valuable to give feedback than modifying components. If you encounter a situation where you can't solve a problem with Lens share it in the Lens Slack channel. Most probably others are experiencing a similar issue and we can create a reusable solution.