Design Systems with Storybook, v2

Real-World Design Systems

Steve Kinney

Steve Kinney

Design Systems with Storybook, v2

Check out a free preview of the full Design Systems with Storybook, v2 course

The "Real-World Design Systems" Lesson is part of the full, Design Systems with Storybook, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Steve shares examples from a real-world design system highlighting the number of styles and variants used in a button component. The Class Variance Authority package is introduced and compared to CLSX. The primary difference is the ability to add type safety for styles in UI components.


Transcript from the "Real-World Design Systems" Lesson

>> All right, so when last we spoke we were talking a little bit about adding and theming kind of when to when to not use tailwind, and the various ways that a button kind of grows over time. And this is actually a version from our actual code base.

Two things I wanna point out here is just, one, the number of classes as your button kinda grows to handle a bunch of other things. And the number of buttons, we've got the primary secondary destructive that goes and we have one's existent table header, an array of sizes.

We can see that even with the tailwind utility classes, it's a helpful way to handle media queries, but as you can still see, it kind of grows a little bit out of control over time. CSLX is one tool for managing all the different styling and stuff that you might have to worry about through a design system.

There's another super interesting library that we leverage heavily called a class variance authority, that is a Loki joke for those of you keeping track at home. And it's a library that does a few things. It allows you to kind of structure your styles in a way that supports this idea of having variants of a button or anything else along those ways.

And it does a bunch of other really interesting things that help when you're building out a design system as well. The other thing that is a value prop is that it is 100% framework agnostic, right? There was a time where our code base for our application was in Svelte and SvelteKit and our website was in react and next, right?

And so you can you share components between the two? And we saw the issue where our dock site is still, in React and we have a bunch of React properties as well. But the two big ones, that really needed to share a lot of style listings, were in two very different frameworks.

So having tooling that helps the styling of your various components. Because it's not just, we have a marketing site and a core app, the Venn diagram began to overlap a little bit, right? And so, for instance, we now have a sign up flow that exists on the marketing website and drops you into the app, right?

So you have new and different demands, and this is one of those stories about whether you intend to or not, you actually end up with a design system, right? We had new and interesting demands where we had to keep a consistent experience, right, across different properties. Implemented at the time in different frameworks, right, and still the next battle and we're not probably converting the dock site because it's just too hard to do that.

Immediately, we do need to spread our design system across multiple frameworks. So having tools that are framework agnostic makes this really easy. Yeah, maybe you need to have a little bit of code that triggers how a drop down menu works in Svelte versus React. But nobody wants to rewrite all the styling and stuff along those lines.

So in being able to apply that across is incredibly powerful. And then also just the ability to like separate it from your code makes it easier to work with in general. Anytime you find yourself working in regular old JavaScript objects and functions, everything from unit testing to IntelliSense to just everything becomes easier.

So it's again, one of these libraries, I've not actually read the code to see how much code it is but could you write a tool like this yourself? You probably could, but why would you when you have shareholder value to go capture? And something like this exists. And so I'll show it to you, let's take a tour of it because it's a lot to write, so we're gonna kinda look at it in a use-case thing.

We'll see it both in my kinda core app and then we'll see a version of the button that I also wrote that we'll bring into our design system as well. So this is the one that we kinda have in our code base and you'll see this roughly similar at the end of the day.

So the first thing is CVA for the class variants authority. You can give it a string, you can give it an array of classes, so far not that much different than what we had with, CLSX, right? Where things become interesting, and this is the only time I regret calling that various button variants variant.

Because variants can be your size, all these things but also it's an overloaded term. Where you can say, okay, well here's the classes that make a primary button, its current color and these BG interactive that's for anything you touch, right? When I told you we were moving to those semantic colors and like the last section, this is an example from you know, our code base.

Interactive is like your buttons, your various radio is the accent on a radio thing, it's that kind of core color. We still referenced white and stuff like that. We are still in the transition so it took a lot to unwind the initial choices there as well. The idea of a danger color so on and so forth.

But like you see so this is what makes the primary button primary. This was what makes a secondary button secondary destructive destructive ghost ghost, table header, so on and so forth, right? The sizes, these are the classes that you might pick, right? Other things that we might choose to do.

And then the default variance. And what's really powerful with this is we'll also kinda see it in React as well, is there is basically two major pieces to class variance story, the function and this type variant props. And I'm gonna talk about it now and then we'll do it again in our code base so that you see it twice.

cuz I think it takes two mental spiritual passes. So this function when we create button styles, or button variance is what we'll call it in ours An then here, you can actually create a type. So how before we did that type, okay, variant is primary, secondary, destructive. Size is like you just write what the classes are and it will generate a TypeScript type that expects a variant, a size, everything that matches up with those classes.

And again, this code is felt, we're gonna look at it and React and you're gonna notice no difference. And so now you have the ability to separate all of the styling in your codebase from the actual framework, and you can use it across multiple Properties you could use it in regular old like HTML.

I guess you need a little bit of JavaScript in there. Right, but you can use it across anything you need and you get all of it kind of like for free and we've got the, all these are set for the type is a little bit easier in react than it is in spelt for it'll be easier and store in file.

But like, you get the basically and we can export this and share it across the code bases.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now