Why we chose Chakra-UI for our design system (part 3)

Yotam Bloom
Melio’s R&D blog

--

In the previous blog (part 2), I explained how we created our theme using Chakra-UI to build our design system.

In this third and final part of this blog series, I will describe how we “wrapped” Chakra-UI components within our project and how we extended them.
Also, we will cover how to create custom components.

Components 🧩

We want to be in control of our components — and for that reason, we want to wrap our components with a simple abstraction.

In this section, we will focus on how to export basic components such as Box, how to extend the Button functionality to match our needs, and how to create a custom component for the icon button.

This is the folder structure that will work with:

Box 📦

Some components will be exported from the Chakra-UI components, for example, Box:

export { Box } from ‘@chakra-ui/react’

The main thing that we gain from wrapping all of our components is if we would wish to extend Box in any way it will already reflect in all the components that use it.

Button 🔘

The button is a great example of how we can extend and customize some of its existing functionalities.

This is a basic example of how we wrapped our button. We mainly wanted to wrap some of the logic that a button has so we will end up with a better API. In this example, we made sure that if we provide a button key from our translations file it will render the proper text:

A few important notes:

  1. We used Chakra-UI forwardRef and not the one from React, because Chakra-UI handles the ref differently.
  2. useStyleConfig is used to get the custom styling we defined in the second part of this blog post.
  3. We didn’t change any of the original button props that Chakra-UI has to provide — we simply extended them.

At Melio, we are very data-driven which means that we use a lot of analytics. This is why we help our developers avoid needing analytic callbacks for each click of a button.

We thus wanted to extend our button abilities and send an event with every click. This is why we needed to “wrap” our button with the following click handler:

We added analyticsPropertiesprop to the button and passed this function to the ChakraButton component. This way, developers don’t need to worry about missing any analytics event.

Now we will need to customize the default loader of our button. In Chakra-UI we have the following default loader:

Chakra-UI default button loader

But the loader in Melio is different — for that, Chakra-UI offers us a way to override the spinner with our own:

This will result in this:

Melio’s button with a custom loader

And here you can look at the full code of this example.

Custom components

Icon Button 🆕

In this section, we will show you how to create a custom component.
A custom component is a component that Chakra-UI doesn’t have or a component that you want to build that’s overridden by the one that Chakra-UI has.

Our icon button design is different from all our other buttons. We wanted to add this component but couldn’t customize our theme in a way that achieved the results we needed. This is due to the fact that Chakra-UI’s implementation of the icon button includes the button from the theme.

This is one variant of our Icon Button design

In order for us to achieve the design displayed above, we will need to create an iconButton.ts file in our theme folder:

Then we will create a custom component that will use the above theme:

We can add the onClickWithEvent that we did in the Button component into the IconButton component.

As you can see we used useStyleConfig which takes the theme that we created and by applying it in the sx property we can override all the styles. We used the as prop to tell it to render a button. In the children property, we gave an option to render the icon if provided otherwise we will render the children.

This can be done on any custom component you wish to create and add to your design system.

Final Thoughts 🤔

After a year of using Chakra-UI as a component library for our design system, here are our top takeaways:

  • The Design system helped us a lot with velocity and consistency.
  • Work between Design, Product, and Engineering became a lot easier when we all spoke the same language. This enabled us to build features faster with fewer “UI” bugs.
  • Developers can ship features faster given they don’t need to deal with styling and responsiveness the majority of the time.
  • Adapting the design system with developers was challenging and the migration phase was not easy.
  • Having dedicated tasks to perform the migration for each component helped us push the design system forward.
  • The Chakra-UI team is responsive and efficiently fixes issues. This is important to consider when choosing a component library.
  • The code in Chakra-UI is simple, modern, and easy to understand when something isn’t working or you need a custom behavior.

In this whole series, we covered why we chose Chakra-UI for our design system (part 1), and how we built our theme (part 2) and created existing and custom components using this library.

I hope that it was helpful and informative, for us it was a successful project which I’m very proud of.

If you made it this far, Kudos 💪

Visit our career website

--

--