How to Add Styled Component Themes to Storybook

Adding styled components support in Storybook.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Storybook for React Apps course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Storybook for React Apps, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Storybook for React Apps
  • [00:00 - 00:11] In the previous lesson, we wrote a few atomic components such as the badge in the review. However, when we look at them on the Storybook, we notice that they don't have global styles applied, which makes them rendered with a missing font.

    [00:12 - 00:23] In order to apply these global styles to Storybook, let's check how it works in the app. Under Source folder, there is App TSX, and this is where everything is being rendered.

    [00:24 - 00:56] So you see that there is a global style element which is sibling to the application routes that renders the components, and essentially this is decorating the components, adding global styles to it. If we go inside of the definition of global style, we see that it's using styled components to create a global style element that has access to the themes, does some CSS reset, as well as sets the font families, and then defines the background color from the tokens, as well as some other rules.

    [00:57 - 01:12] In the Decorators lesson, we learn that decorators can be used in Storybook to provide extra functionality or visuals to components. Given that we want every component in our Storybook to have global styles applied to them, it really seems like we need to add a decorator for it.

    [01:13 - 01:26] And because we're going to add maybe a bunch more in the next lessons, let's create a file under Storybook folder that will hold all of the decorators. Let's call it decorators.tsx and start writing a decorator for the global style .

    [01:27 - 01:42] So the first thing that we have to do is to actually import the global style, which is outside of the Storybook folder, under source, styles, and global style. Then we can import the global style element.

    [01:43 - 01:53] There is a type from Storybook React, which helps us define the types for a decorator. It's called a decorator, fn as in function.

    [01:54 - 02:10] And then we can start creating our decorator function. What is a decorator function, if not just a wrapper that receives an element and then renders something in the element itself.

    [02:11 - 02:18] And then you can add whatever you want, right? So instead of element, I'm going to be calling this story fn as in the story function.

    [02:19 - 02:34] And the name of the wrapper should reflect the purpose of what it's made for, which is it's going to be wrapping the element with, let's say, a theme. And the story element is going to contain pretty much what we had here in the f gsx.

    [02:35 - 02:42] So if this is supposed to be a story, the global style is going to be a sibling of it. So we just do global style.

    [02:43 - 02:52] And we have our very first decorator. And in fact, because we're going to have a bunch of decorators, oh, and actually we should be typing this out.

    [02:53 - 03:02] So let's just type it. And because we're going to be exporting a lot of decorators here, let's add them to an array called global decorators.

    [03:03 - 03:16] And then it's an array containing with theme. And because we want to apply these decorators into every story, we should be importing this property that we created under preview TS.

    [03:17 - 03:29] So this already contains some configuration for certain things of the storybook . And all we have to do is import from dot slash decorators.

    [03:30 - 03:42] And then the property is called global decorators. Once we import it, we could put this here at the bottom and write export const decorators equals global decorators.

    [03:43 - 03:57] Essentially, storybook will receive the decorators from this named property in the preview and apply to every single story. So once we save it and go back to storybook, then we see that something failed.

    [03:58 - 04:12] In order to like understand what's going on, we could bring the dev tools on the panel, open console, and then we're going to see a bunch of errors. And we see cannot read properties of undefined.

    [04:13 - 04:20] And over here, it says global style. So if we click here, actually, it's pointing us to the exact error.

    [04:21 - 04:32] So when we go into the actual global styles file, let me quickly go find it. We see that it needs a theme because it comes from style components.

    [04:33 - 04:55] So in order to actually get the theme, as we can see in the app TSX, the style components also provides a theme provider where you can pass the theme that contains all of your design tokens. And in our decorator that we just created, we are essentially just using the global style element, but we're not providing the themes.

    [04:56 - 05:01] So in order to fix that, it's pretty simple. We just need to do pretty much the same thing which is over here.

    [05:02 - 05:17] So we need to import also the theme, which comes from source styles and then theme. And then we could maybe start using the like theme.

    [05:18 - 05:30] We also need to import a theme provider from style components. And that is called theme provider.

    [05:31 - 05:48] And essentially what we need to do now is to add the theme provider here and at the bottom and pass a theme property, which is going to be the like theme. Now when we go back to storybook, we see that the fonts are correct.

    [05:49 - 05:52] And that's pretty great. Let me close over here.

    [05:53 - 06:08] There's actually one more thing that we can do, which is when we go back to the badge component. We see that the styles are actually hard coded, but now that we have a theme access in every component in storybook, we can actually improve it by using the design tokens.

    [06:09 - 06:19] So in fact, if we add an object here, we get access to the theme property from style components. And then we can get stuff like color and border radios, for instance.

    [06:20 - 06:37] And instead of having this specific hard coded value, let's use, let's interpol ate it with color dot badge background. And for the border radios, let's use border radios dot extra small.

    [06:38 - 06:50] And for this span color, let's do color dot badge text. Apart from this, we can also improve the fact that we're just using spans for texts.

    [06:51 - 07:00] And we actually have a typography element that we can use. So let's import from dot dot slash typography.

    [07:01 - 07:10] And there isn't an element called body, which we can use instead of this span. So let's trade this for body.

    [07:11 - 07:16] And the body contains a few properties. We still want this to be a type of span.

    [07:17 - 07:27] And we want the size of it to be small. So once we finalize this and go back to storybook, we see that it looks much, much better.

    [07:28 - 07:36] So let's do something similar for the review component as well. We'll find it under source components and review.

    [07:37 - 07:44] And what we need to do over here, it's pretty similar. So let's also select the story components.

    [07:45 - 07:53] And let's go back to the code. What we need to do is to first of all import styled from styled components.

    [07:54 - 08:06] We're also going to be using instead of a div, we're going to be using typ ography component. So let's import body from dot dot slash typography.

    [08:07 - 08:16] And in this case, we do need to create a small wrapper for the review component . So let's just do something like this.

    [08:17 - 08:34] We're going to create a small div that has a couple of styles. So this play that's going to be flex align items to the center as well as justify content flex start just to have things properly aligned.

    [08:35 - 08:42] So we get this wrapper and then we add it at the bottom. Let me just wrap this out on a parentheses.

    [08:43 - 08:56] Add it like this and over here and a wrapper elements. And instead of using a div, we're going to replace this with a body.

    [08:57 - 09:06] The same goes for here. We also want this to be a type of span as well as use a size small.

    [09:07 - 09:18] The final thing we want to do here is also to add a class name called review dash text. And then we should be done.

    [09:19 - 09:37] So once we're back to storybook, we see that the review component looks nice and neat and has all of the styles applied. And now that we actually added the theming to the decorators, that means that the components will have access to the whatever tokens you're passing.

    [09:38 - 09:53] And if we go inside of the theme for our file, we see that we have some colors, some space units, some border radios and such. And the theme is actually divided into two like theme and dark theme.

    [09:54 - 10:16] So if we go back to the decorators file and instead of passing a light theme, we actually were to pass a dark theme, then you would actually see storybook rendering stuff in dark mode, which is really cool. And that will go for basically any story that uses the tokens because they will be switched at runtime between the dark mode and light mode.

    [10:17 - 10:30] Well, but for now, let's just keep the like theme and we can continue further in the next lessons. So effectively, we learned how to create a decorator to support theming in our storybook.

    [10:31 - 10:40] And we essentially can apply the same concept for all kinds of things that we might need and encounter throughout the next lessons. So I hope you enjoyed so far and I'll see you in the next one.