Walks through building a consistent design system on top of React and Material UI. Covers component structure and design tokens as the foundation for a reusable UI library.
Published 2021-06-22

5 min readJun 22, 2021
\--
Press enter or click to view image in full size
Modern design systems rely heavily on rich UI component libraries. They promote code reusability, enable consistency in design (in and across apps) and speed up overall development.
This article shares how I used React Material UI with Bit open source platform to create a custom design system focused on consistency with high governance.
You can preview each independent components by visiting the Bit collection URL.
https://bit.dev/enlear/react-material-design/
Overview of the design system: https://bit.dev/enlear/react-material-design/
Here, each component in the design system is authored, versioned, and shared individually and not as part of a single monolithic library, that creates countless benefits such as;
As we all know React Material UI provides a range of UI components that are ready to use. However, think of a scenario where you want to add a React button component, and you know it supports different attributes. You can have a button with rounded edges, a button with a label, a button with an icon, or even a button in disabled status.
Press enter or click to view image in full size
Different button variants in React Material UI
Though it’s one of the prime objectives of a UI library to allow customization, if we expose this flexibility to developers, it could adversely affect the consistency of the user interfaces.
But we have the options to restrict this behavior. One approach is to build an abstraction on top of React Material UI components by exposing only a given set of properties.
This what I refer to as wrapping the components.
Following this approach clearly brings control over each UI component props and actions.
Besides, there are several objectives I wanted to meet with the design system.
For the design system, I’ve developed the following categories to group UI components at different levels.
Then you might wonder why I chose to group them in this way.
Join Medium for free to get updates from this writer.
Remember me for faster sign in
For lower-order components such as UI/Inputs, Layouts, and Surfaces, I’ve followed the same structure as in React Material UI library.
For higher-order components, I’ve introduced Widgets and Pages out of thin air. 🙂
At first, I got stuck on choosing the basic building blocks for the design system. I’ve decided to select a subset of components from React Material UI wrap them to create the Button, Radio, Select and Text field as the foundation. These components you can find under the UI/Inputs, as shown below.
https://bit.dev/enlear/react-material-design/ui/inputs/button/~code/button.tsx
Button component in the design system at bit.dev
For instance, I don’t want developers to make spontaneous decisions on how a button should look or behave, breaking the consistency.
Though the button’s functionality is limited, we can gradually add more functionality having complete control since it’s the only button reused elsewhere in the application. Besides, it also reduces the coupling of React Material UI with higher-order components.
Then, gradually the higher-order components were defined. The below example shows how the product page components look like.
https://bit.dev/enlear/react-material-design/pages/products
Products page component composition in bit.dev
https://bit.dev/enlear/react-material-design/pages/products/~code/products.tsx
Product page code example in bit.dev
Furthermore, to understand its dependencies, let’s look at the complete dependency graph of the products page.
https://bit.dev/enlear/react-material-design/pages/products/~dependencies
Dependency graph of product page component
As you can see, the design system clearly reuses its foundational building blocks, which is a good sign that it’s working.
Typically theming applies to basic UI components. With React Material UI, each component inherits from the default theme. So if we can override that, we can implement custom themes.
That’s precisely the theme provider global overrides supposed to do.
Following are some of the properties we can override by creating a custom theme provider.
https://material-ui.com/customization/theming/#theming
Theme overrides in React Material UI
For example, suppose I override the “primary” property of the palette object inside a custom theme provider. As a result, it directly overrides the color of the button component in the design system.
Press enter or click to view image in full size
Overriding primary color palette in React Material UI
I believe design system should become the norm to bridge the gap between designers and developers to establish consistency in frontend development.
However, in the current design system, I’m still doubtful whether to wrap the React Material UI components or not, which has both ups and downs. If you have a different opinion, please do mention it in the comments below.
Some Final Tips,
Thank you for reading !! 🙂
Originally published on Level Up Coding.