Find Out If Your Design System Is Better Than Nothing

Rate this content
Bookmark

Building a design system is not enough. Your dev team has to prefer it over one-off components and third-party libraries. Otherwise, the whole effort is a waste of time. Learn how to use static code analysis to measure if your design system wins over the internal competition and data-driven ways to improve your position.

20 min
21 Jun, 2022

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Building a design system without adoption is a waste of time. Grafana UI's adoption is growing consistently over time. The factors affecting design system adoption include the source mix changing, displacement of Homebrew components by Grafana UI, and the limitations of Grafana UI's current state. Measuring adoption is important to determine the success of a design system. The analysis of code through static code analysis tools is valuable in detecting and tracking component usage.

1. Measuring Design System Adoption with Grafana UI

Short description:

Design system is worthless if not used. Building a design system without getting sufficient adoption is a waste of time and effort. In this talk, I will tell you how to measure the adoption of a design system. Grafana is a DevOps monitoring platform with a design system called Grafana UI. Let's take a look at how well Grafana UI is doing. The line goes up. Number of usages grows consistently over time. The reason you don't know is competition.

♪♪♪ Design system is worthless if not used. Design system is a tool, it's not enough to exist. It has to actively be used to make the product better or help deliver it faster. That's the only way for a design system to be valuable. Building a design system without getting sufficient adoption is a waste of time and effort.

My name is Arseniy, I'm a Solution Architect at Rangel Amsterdam. In this talk, I will tell you how to measure the adoption of a design system based on a metric I set up recently for one of our clients. Conversation about metrics requires data. Showing you data from a corporate client is unfortunately not possible, so I found an open source substitute. I will use Grafana as an example. If you don't know, Grafana is a DevOps monitoring platform. It's an old and big project. It was rewritten from Angular to React starting around 2018. It has an ecosystem of plugins and most importantly, for the stock, Grafana has a design system. It's called Grafana UI. In their storybook intro, they say that they built it to get a shorter development cycle and a consistent user experience. These goals are in line with what you'd expect to find in a corporate design system. I want my products to look like my products and I want to build them faster.

Let's take a look at how well Grafana UI is doing. On this chart, we're tracking how a project and its ecosystem evolved and how they adopted a design system. Horizontal timescale is five years. Measurements are taken at weekly intervals. Vertical number is Grafana UI component usages. Usage is when a component is referenced in code. We'll discuss later what it means but simplified, and it's when you mention a component in a JSX tag. For the sense of scale, last week at the right edge of the chart, Grafana UI components were used more than 7,000 times across Grafana itself and 290 of its plugin code bases.

What picture does this chart show you? The line goes up. Number of usages grows consistently over time. Is this good for the design system? Does this mean the design system is getting continuously adopted? The answer is you don't know. The reason you don't know is competition.

2. The Role of Design System and Homebrew Components

Short description:

Developers have a choice of how they build things, whether using third-party libraries, building their own components, or utilizing a design system like Grafana UI. Homebrew components, which are low-level components implemented directly in the product code base, are also important to consider. By analyzing the chart, we can see that both the design system and Homebrew components are growing, indicating a healthy project and ecosystem.

I'm an engineer. I can use a design system. I can use third-party libraries or I can build my own components. Developers have a choice of how they build things. This is particularly true for the open source plugins in this analysis. If I build a plugin and host it on my own GitHub account, who can force me to use Grafana UI? The only option to affect my choice is to make a good design system and make it easy to use.

Even if your product doesn't use any third-party libraries, in any project there are going to be Homebrew components. Homebrew are the low-level components implemented directly in the product code base. You build your own button, that's Homebrew. It's very important to focus on the low-level components. We're not looking to find every possible component usage. We're looking for the competition. Component Online 2 is not Homebrew because it's compositional, it only uses other components. Compositional components are expected in any code base and don't compete with the design system. Component Online 1, on the other hand, is Homebrew, it uses lowercase jsx tag as opposed to capitalized one. That way, we know it deals with a raw markup. Because it deals with raw markup, we count it as Homebrew.

Now that we know what we're looking at, let's add Homebrew to the chart. This is the same chart as before. Same axis, same data, except with Homebrew usages added on top. I want to point out the scale once more. We're looking at combined 11,000 component usages at the right edge of the chart, across 291 repo. Total shaded area is almost a million usages, though they're not unique since we're tracking code over time. What can you see on this chart? Gray area at the top, representing Homebrew, starts before red area, representing Grafana UI. At first, there was no Grafana UI. Both lines are growing. While the user design system is growing, so does Homebrew. The fact that the two lines are growing means that the project and the ecosystem are growing. They look healthy. The shapes look pretty similar, in particular, over the last year.

3. Design System Adoption Factors

Short description:

The bumps on the lines indicate changes in component usage. The shape of the lines may not always mirror each other, suggesting a change in the component source mix. By analyzing the source mix changing over time, we can understand the factors affecting design system growth. The chart shows the proportion of Homebrew to Grafana UI usages, indicating the displacement of Homebrew components by Grafana UI. Developers are increasingly choosing to use Grafana UI over Homebrew. The chart also reveals the initial absence of Grafana UI, a significant jump when existing components were pulled into it, and a recent slowdown in displacement due to the limitations of Grafana UI's current state.

The bumps on these lines are features every significant change set adds a bump or a dip to the line, because it means components are used more or removed from the code base. But notice that the shapes are not always mirroring each other. Noticeably around the 721 mark. Lines not being similar, means a component source mix is changing.

Imagine you have two buckets, Homebrew and Grafana UI. You take components from both buckets and compose to make your feature. Buckets are your sources. How much you take from the buckets is your source mix. Source mix changing means you're taking more or less from one of the buckets than you did before. We can infer from this chart, the two sets of factors affecting design system growth. How the project growth grows and how the design system itself is doing.

To isolate the design system adoption from the project growth and other factors, we have to look at how the source mix changes over time. And this, in my opinion, is the single most important chart for a design system. This is a source mix changing over time. It's a proportion of Homebrew to Grafana UI usages. The size of a code base is not fixed. It grows and sometimes shrinks over time, but each feature has limited opportunities to use the components. Out of the set of competing components doing probably the same thing, you're only going to use one in each case. This means choice of the component source is a zero sum game. If you use a design system, you're not using Homebrew and vice versa. So the chart you're looking at shows displacement. It represents Grafana UI taking over the choices developers make when building things. More and more, developers are choosing to use Grafana UI over Homebrew components.

Some things you can notice about this chart. In the beginning, there was only Homebrew, Grafana UI did not yet exist. Then you see drastic jump when the existing components are pulled into Grafana UI for the first time. The project was still small then, so this creates a big change in proportion. When you see a period of growth for a couple of years, and over the last year, displacement almost stopped. Grafana UI reached the limit of what people can do with it in its current state. The mirroring of the two lines that you've seen on the previous chart is almost perfect for the last year because the source mixed did not change.

4. Measuring Design System Adoption

Short description:

Grafana UI reached a state where each new feature uses the same mix of a design system and Homebrew components. The chart shows team preference for the design system over the competition. It also accounts for availability. If your design system fails to displace the competition, the share it takes across the component usages will diminish over time. If the design system is successful at displacing the competition, that's how you know it's doing well. Up is good. Down is bad. What's an appropriate sideways level? For a general purpose design system ideally you should reach a level where there is no other homebrew components except for snowflakes. If you only have snowflakes among homebrew components you're doing a fantastic job.

Grafana UI reached a state where each new feature uses the same mix of a design system and Homebrew components, even if the components themselves are different. Why is this chart so much better than the previous ones? Source mix is independent of project growth, team size, level of investment, etc. You double the team size tomorrow, the chart remains valid. It removes any volatility due to features, the only changes are the source mix, nothing else.

Basically, it shows team preference for the design system over the competition. Interestingly, it also accounts for availability. If I'd like to use a design system component, but I can't find it, I am more likely to use homebrew. For a business or a product, you might look at the market share. This chart is market share for design system within the project.

Is your design system better than nothing? If you do nothing, if you don't build a design system at all, the product will still exist. The features will still be built using other components. If your design system fails to displace the competition, the share it takes across the component usages will diminish over time from the starting positions. That way project grows faster than the design system gets adopted and features don't use it much. If the design system is successful at displacing the competition that's how you know it's doing well. Which brings me to the basic property of this metric. Up is good. Down is bad. If the chart goes down for a while, something is wrong. If the chart goes up, keep doing what you're doing. Though it cannot go up forever. No matter what the coach says you can't give more than 100%. Even if you do everything absolutely right line will go sideways at some point.

What's an appropriate sideways level? For a general purpose design system ideally you should reach a level where there is no other homebrew components except for snowflakes. Snowflakes are those truly unique one-of-a-kind homebrew components. Imagine you're building a landing page for a million-dollar ad campaign. It's okay to have a bunch of unique components specifically for that situation. Having snowflakes in the project is okay and probably unavoidable. If you only have snowflakes among homebrew components you're doing a fantastic job. You might not reach that level. If you only did the very basics don't expect line to go too high.

5. Factors Affecting Design System Adoption

Short description:

If your code base has too much legacy, the line won't go high fast. The level of adoption depends on goals and specific use cases. The design system requires governance and collaboration across the organization. Lack of adoption can occur at any point in the decision-making process. This analysis is valuable and should be part of the governance process. Computers can read code through static code analysis. Tools that read code programmatically are commonly used.

If your code base has too much legacy don't expect the line to go too high too fast either because refactoring legacy is slow so displacing legacy is slow. And the level you reach depends on goals. If you're focusing on a specific use case for example getting product images just right for e-commerce then it's okay to not get too much adoption relative to all the homebrew in the project.

If you have a specific focus you need to adjust your definition of the competition to get meaningful metric. Remember that homebrew definition so far was any component rendering raw markup. User share is a code based metric. If it doesn't go as high as you want you might be tempted to call out those pesky developers for meddling with the adoption success. That's not correct. Design system requires governance deciding what goes in and what doesn't. It requires a lot of collaboration between different people across the organization designers, developers, and product owners. Lack of adoption might be caused at any point in the decision-making process. If a designer doesn't like the system they will not incorporate it into the designs so the developer won't use it either. This measurement sits at the tail end of the development process so it's affected by all the choices involved in it.

The analysis is still valid though because in the end, software product is code and the design system is shipped as part of it. For this analysis to be useful it has to become a part of your governance process and for that it has to be cheap and repeatable. You should be able to run it every sprint to see how things change, to react, and to plan further work. Fortunately, we can automate it. Here's a famous example of gibberish. If I ask you to tell me what the statement is about you should be able to say that it's about ideas doing something. You should be able to find the subject. Notice that the phrase is designed to have no meaning yet we're able to make some judgments about it based purely on syntax.

Surprise! Computers can read code. In practical terms it means code is formal. It has strict syntax. It has to be formal for the machines to run it. We can teach a computer to read code and find patterns in the structured statements. This is called static code analysis. Just like with Chomsky's nonsense we don't have to run the code to figure out what it's doing. It's enough to look at code. You're probably already using tools that read the code programmatically.

6. Detecting Homebrew Components and Usages

Short description:

Your linter does static analysis to find issues without having to understand what your code is doing. To detect a Homebrew component, we'll look for functions with lowercase JSX tags. The code you see also creates a React component. I promised earlier to tell you what is a usage. Tag online2 references a button identifier defined on line 1. JavaScript is typically not as simple as that. Indirect usage like this is still a usage of a button. Take two files, one where you export the button and one where you import it.

Your linter does static analysis to find issues without having to understand what your code is doing. Let's take a look at the syntax of a component. We've seen this code before. How exactly do we know that homebrew is indeed a Homebrew component? React component is a function returning JSX or a class with a render function if you're old school. Both Homebrew and not Homebrew are components. They're both functions returning JSX.

On top of that Homebrew mentions a lowercase tag. Let's reiterate. To detect a Homebrew component, we'll look for functions. In functions, we look for lowercase JSX tags. If the function contains a lowercase tag, it's a Homebrew component. Same for classes. When doing this analysis, we assume the code is valid because it has to be correct to get shipped to production. If you're shipping invalid code to production you've got bigger problems and I can't help you.

On top of that we assume the code is sane. It's really hard to write a program that would analyze all possible Javascript. The code you see also creates a React component. I don't think it's reasonable to try and parse code like this because this code is not sane. Good thing that humans tend to not be able to read code like this very well either. If someone on your team is shipping this to production you've got bigger problems and I can't help you. I promised earlier to tell you what is a usage. Tag online2 references a button identifier defined on line 1. Such a reference is a usage of a button component. JavaScript is typically not as simple as that. So things can get a little bit more complicated. Indirect usage like this is still a usage of a button. We've taken a button, assigned it to another variable and referenced that variable. This still counts. Take two files, one where you export the button and one where you import it. There are multiple ways to import including aliases, namespaces and re-exports.

7. Importing and Tracking Component Usage

Short description:

Importing and tracking usage of components is essential. Usage can be determined based on package exports and subsequent usage. Higher order components can also affect usage count. Usage in code is not well-defined and depends on syntax. The tool used for tracking is called Radius Tracker. To calculate the metric, find homebrew components, design system imports, and collect usages. Adjust weights by component complexity for a meaningful chart. Build what is valuable for your team and measure usage share percentage. The open-source Radius Tracker tool by Wrangle can help with the analysis.

Importing is extremely common and we have to keep track of it. Usage of the button on line 6 should count. Notice it's possible to track usage of a button starting from the import at line 5. We don't need to know what the button is, only if the package exports something called button and that thing later gets used. This way we can track usages of a design system imported as a package.

You have a button, you put it into the object and spread it into props. You have now passed the button as a render prop. It's still a usage of a button. We don't know what happened to the button inside the component but we know that the button is likely to be used. Another common use case is higher order components. Notice that the button is used not when the higher order component is created on line 5 but when it is used on lines 6 and 7. Every time the HOC is used the original button component is also used. This code counts as two usages of the button.

The reason I'm going through these cases other than to show off the sophistication of my tracking tool is to point out that usage in code is not a well-defined concept. For the machine usage only exists at runtime. We're not analyzing for dead code. We're not figuring out how often something gets rendered for a user in the browser. If we're looking at the static code we have to define what usage means based purely on the syntax. Given all the ways JavaScript can be written that definition depends on what you consider usage. My definition is implemented in the tool that I'm using to collect the data. It's called Radius Tracker. I'll give you a link at the end.

Now that you know how to detect homebrew and find usages here's how to calculate the metric. Find homebrew components. Find design system imports. Collect usages of both. Calculate the source mix proportion. And repeat for historical commits. I've used button as an example throughout this talk so far. But not all components are created equal. If you compare an abstract button and a date picker you'll probably find that each use of a date picker is worth much more than the use of a button because date picker is a bigger more complicated component. For a more meaningful chart you have to discount simpler components. This means adjusting the weights by component complexity. The charts you've seen before treat all components the same. For the client I mentioned in the beginning we ignored all usages of components like box or typography because those aren't valuable even if significantly over represented in the code base. If you take one thing from this talk build what is valuable for your team and then measure the usage share percentage to see how much people prefer what you're doing over the internal competition. To run this analysis yourself grab the radius tracker we wrote in Wrangle it's open source and I suggest you check it out. Ask me for advice and reach out to Wrangle for practical help.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Top Content
Design systems aim to bring consistency to a brand's design and make the UI development productive. Component libraries with well-thought API can make this a breeze. But, sometimes an API choice can accidentally overstep and slow the team down! There's a balance there... somewhere. Let's explore some of the problems and possible creative solutions.
TechLead Conference 2023TechLead Conference 2023
35 min
A Framework for Managing Technical Debt
Let’s face it: technical debt is inevitable and rewriting your code every 6 months is not an option. Refactoring is a complex topic that doesn't have a one-size-fits-all solution. Frontend applications are particularly sensitive because of frequent requirements and user flows changes. New abstractions, updated patterns and cleaning up those old functions - it all sounds great on paper, but it often fails in practice: todos accumulate, tickets end up rotting in the backlog and legacy code crops up in every corner of your codebase. So a process of continuous refactoring is the only weapon you have against tech debt.In the past three years, I’ve been exploring different strategies and processes for refactoring code. In this talk I will describe the key components of a framework for tackling refactoring and I will share some of the learnings accumulated along the way. Hopefully, this will help you in your quest of improving the code quality of your codebases.

React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
React Advanced Conference 2022React Advanced Conference 2022
22 min
Monolith to Micro-Frontends
Top Content
Many companies worldwide are considering adopting Micro-Frontends to improve business agility and scale, however, there are many unknowns when it comes to what the migration path looks like in practice. In this talk, I will discuss the steps required to successfully migrate a monolithic React Application into a more modular decoupled frontend architecture.
React Advanced Conference 2023React Advanced Conference 2023
22 min
Power Fixing React Performance Woes
Next.js and other wrapping React frameworks provide great power in building larger applications. But with great power comes great performance responsibility - and if you don’t pay attention, it’s easy to add multiple seconds of loading penalty on all of your pages. Eek! Let’s walk through a case study of how a few hours of performance debugging improved both load and parse times for the Centered app by several hundred percent each. We’ll learn not just why those performance problems happen, but how to diagnose and fix them. Hooray, performance! ⚡️

Workshops on related topic

React Summit 2023React Summit 2023
137 min
Build a Data-Rich Beautiful Dashboard With MUI X's Data Grid and Joy UI
WorkshopFree
Learn how to put MUI’s complete ecosystem to use to build a beautiful and sophisticated project management dashboard in a fraction of the time that it would take to construct it from scratch. In particular, we’ll see how to integrate the MUI X Data Grid with Joy UI, our newest component library and sibling to the industry-standard Material UI.
Table of contents:- Introducing our project and tools- App setup and package installation- Constructing the dashboard- Prototyping, styling, and themes - Joy UI features- Filtering, sorting, editing - Data Grid features- Conclusion, final thoughts, Q&A
React Summit Remote Edition 2021React Summit Remote Edition 2021
87 min
Building a Shopify App with React & Node
Top Content
WorkshopFree
Shopify merchants have a diverse set of needs, and developers have a unique opportunity to meet those needs building apps. Building an app can be tough work but Shopify has created a set of tools and resources to help you build out a seamless app experience as quickly as possible. Get hands on experience building an embedded Shopify app using the Shopify App CLI, Polaris and Shopify App Bridge.We’ll show you how to create an app that accesses information from a development store and can run in your local environment.
React Summit 2022React Summit 2022
147 min
Hands-on with AG Grid's React Data Grid
WorkshopFree
Get started with AG Grid React Data Grid with a hands-on tutorial from the core team that will take you through the steps of creating your first grid, including how to configure the grid with simple properties and custom components. AG Grid community edition is completely free to use in commercial applications, so you'll learn a powerful tool that you can immediately add to your projects. You'll also discover how to load data into the grid and different ways to add custom rendering to the grid. By the end of the workshop, you will have created an AG Grid React Data Grid and customized with functional React components.- Getting started and installing AG Grid- Configuring sorting, filtering, pagination- Loading data into the grid- The grid API- Using hooks and functional components with AG Grid- Capabilities of the free community edition of AG Grid- Customizing the grid with React Components
JSNation 2022JSNation 2022
41 min
Build a chat room with Appwrite and React
WorkshopFree
API's/Backends are difficult and we need websockets. You will be using VS Code as your editor, Parcel.js, Chakra-ui, React, React Icons, and Appwrite. By the end of this workshop, you will have the knowledge to build a real-time app using Appwrite and zero API development. Follow along and you'll have an awesome chat app to show off!
GraphQL Galaxy 2021GraphQL Galaxy 2021
164 min
Hard GraphQL Problems at Shopify
WorkshopFree
At Shopify scale, we solve some pretty hard problems. In this workshop, five different speakers will outline some of the challenges we’ve faced, and how we’ve overcome them.

Table of contents:
1 - The infamous "N+1" problem: Jonathan Baker - Let's talk about what it is, why it is a problem, and how Shopify handles it at scale across several GraphQL APIs.
2 - Contextualizing GraphQL APIs: Alex Ackerman - How and why we decided to use directives. I’ll share what directives are, which directives are available out of the box, and how to create custom directives.
3 - Faster GraphQL queries for mobile clients: Theo Ben Hassen - As your mobile app grows, so will your GraphQL queries. In this talk, I will go over diverse strategies to make your queries faster and more effective.
4 - Building tomorrow’s product today: Greg MacWilliam - How Shopify adopts future features in today’s code.
5 - Managing large APIs effectively: Rebecca Friedman - We have thousands of developers at Shopify. Let’s take a look at how we’re ensuring the quality and consistency of our GraphQL APIs with so many contributors.
TypeScript Congress 2023TypeScript Congress 2023
131 min
Practice TypeScript Techniques Building React Server Components App
Workshop
In this hands-on workshop, Maurice will personally guide you through a series of exercises designed to empower you with a deep understanding of React Server Components and the power of TypeScript. Discover how to optimize your applications, improve performance, and unlock new possibilities.
 
During the workshop, you will:
- Maximize code maintainability and scalability with advanced TypeScript practices
- Unleash the performance benefits of React Server Components, surpassing traditional approaches
- Turbocharge your TypeScript with the power of Mapped Types
- Make your TypeScript types more secure with Opaque Types
- Explore the power of Template Literal Types when using Mapped Types
 
Maurice will virtually be by your side, offering comprehensive guidance and answering your questions as you navigate each exercise. By the end of the workshop, you'll have mastered React Server Components, armed with a newfound arsenal of TypeScript knowledge to supercharge your React applications.
 
Don't miss this opportunity to elevate your React expertise to new heights. Join our workshop and unlock the potential of React Server Components with TypeScript. Your apps will thank you.