Don’t repeat yourself. It’s a principle that engineers strive to adhere to — preventing code duplication by abstracting shared functionality out into its own place.

At Hy-Vee, we reached a point where we were spinning up new teams extremely quickly and needed to maintain consistency across products. How could we ensure every person created a button that looked and functioned the same way across all digital properties?

Our first step in tackling this problem was having UI/UX define a style guide that all consumers should implement. We needed a simple approach to ensure the adoption of our style guide and a set of shared components consumers could use without having to worry about styling.

Developing a Plan

We decided to build a reusable UI component library which will be consumed in all of our client-facing applications. This project had a few main goals:

Create consistency across the organization

All digital properties should look and feel the same, implementing our agreed upon style guide.

2. Improve the overall quality of our codebase

Having a shared set of UI components means less custom code for consumers.

We can ensure all components meet our accessibility requirements.

Components become hardened by multiple teams contributing to bug fixes and improvements.

3. Increase developer proficiency

Developers not specialized in CSS don’t have to worry about CSS quirks or cross-browser issues.

Allow us to ship new products and rewrite legacy products faster.

Decrease the amount of time it takes new employees to build UIs correctly.

To accomplish these goals, we chose to use styled-components as the base of the library. styled-components uses ES6 tagged template literals and CSS to allow you to write real CSS code in your components instead of using JS objects.

It’s used by companies like Bloomberg, Atlassian, Reddit, Patreon, Target, Coinbase, and more. There’s a variety of CSS in JS solutions, as outlined very succinctly here. After reviewing this list and reading the styled-components documentation, it seemed like a no-brainer for our use case. Some big wins for us:

Feels like writing traditional CSS vs. JavaScript objects

React & React Native support

Auto-prefixing vendor styles

Scoped styles eliminate global CSS conflicts

Building the Library

Let’s take a look at a simple example: a button.

If it looks familiar, that’s because it should. It’s truly CSS without anything extra on top. Using the template string, it invokes the styled.button function and passes in the CSS string. This button makes it extremely easy for consumers to use (as shown below).

A component library doesn’t have just one type of button, though. Let’s explore how we can extend this BaseButton component.

We can pass the existing BaseButton into styled to build our primary colored button using our main brand color.

Using Props

Extending isn’t the only way we can modify our base component. We can also conditionally change styles based on the props passed in. Let’s explore adding a disabled state to our Button component.

Then, we can pass in disabled as a prop when invoking the component.

Utilizing JavaScript & React