Set Storybook Themes With Decorator Global Values and Parameters

Making decorators smarter with the use of globals and parameters to allow for an interactive theme switching experience.

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 created a decorator to add theme support to Story book. Although it works well, in order to switch the themes, like from light to dark, we actually need to make code changes, which isn't that great.

    [00:12 - 00:28] Storybook decorators not only have access to the story elements, but also to a story context. When we check the decorator's page in a documentation website for Storybook, we see that the second argument to a decorator function is the Story context, which contains a bunch of keys.

    [00:29 - 00:36] In particular, we could use Globals and Perimeter to our advantage. Let's start with Globals.

    [00:37 - 00:48] We see that Globals are essentially global data that is persisted across Stories. And you can use Globals in combination with Add-on Toolbars, which is part of the Essential Add-ons.

    [00:49 - 01:04] And that will allow you to have a very interesting experience, such as when you see the Background's Add-on or the Viewport's Add-on, you have options to choose in this toolbar, you could achieve the same for your own custom toolbar. In the documentation, we see an example that explains you how to do that.

    [01:05 - 01:17] So let's just copy-paste this and see what happens. We go to Storybook Preview, and at the bottom, we paste the code.

    [01:18 - 01:28] The code does the following. We export a new property called Global Types that is an object containing a first key called Theme.

    [01:29 - 01:43] We provide a name to it, a description, a default value, and the toolbar, which is the most important part, we say that there is an icon, which is a circle hollow. It contains a list of items, and we want to show the name.

    [01:44 - 02:02] Storybook will pick this up, and it will essentially use that configuration to build a new UI element in the toolbar, which is called Theme. If we click on it, we see we now have a light and dark options, light being the default already selected, which is awesome.

    [02:03 - 02:16] If we select dark, though, nothing happens. And the reason for that is because we only are defining what the Globals for the theme should be, but we're not hocking that data up to our decorators.

    [02:17 - 02:33] So let's go back to the decorators part, and now we're going to receive a new attribute called context. Let's turn this into a more complex function and start doing something with this.

    [02:34 - 02:59] Now, we create a theme variable, which is going to be used based on what we're passing in the context, and context contains, once again, the Globals property, and now in order to access the key that we provided here, it's just going to be called Theme. So we call this Globals.theme, and from there, we can decide whether we want to render a dark theme or a light theme.

    [03:00 - 03:22] So let's go here at the top and import the dark theme as well, and let's create a new variable called StoryTheme, which is going to be, is the theme equals dark, then we want to render the dark theme. Otherwise, we want to render the light theme, and then we get this theme and pass down to the story.

    [03:23 - 03:36] So when we go back to Storybook, and we now select the theme, we see that everything changes. And in fact, because this is a global value, once we go to a different story, the theme is also the same.

    [03:37 - 03:55] If we switch back to Light, it also is affected here. And the reason that worked is because whenever you change any global data, the decorators will re-render, thus the Globals.theme value will change, and we will be able to re-render the components with a new theme.

    [03:56 - 04:06] And this is great. However, what if I don't want to necessarily have to click here to set the theme to Story, but I want to create a new story of my component and hard-code it to a specific theme.

    [04:07 - 04:18] Is that even possible? Well, absolutely. If we go back to the decorators part, we know that the context also has access to the parameters key, and we can use that to our advantage.

    [04:19 - 04:24] So go going to our batch.story.csx. We can create a new story.

    [04:25 - 04:35] Let's suppose this is going to be always in dark theme, so we're going to call it dark theme. This is the moment where we can define a property called parameters.

    [04:36 - 04:43] And normally the key to parameters, they are used by storebook atoms. However, we could use this for ourselves as well.

    [04:44 - 04:52] And over here, we can define any key that we want. So let's just suppose the name of the key is called theme, and the value is dark.

    [04:53 - 05:06] When going to the decorators, instead of just using global.theme, we're going to first of all check whether context.parameters.theme exists. And if they don't, we fall back into the global.

    [05:07 - 05:21] This way, our story will always be overruling the context.global, and we will have the following experience on Storybook. We now see the default theme element, and now we have the dark theme one.

    [05:22 - 05:34] And it's great because now we can set the themes for all of the stories we want using this, but we can also hard code specific themes in the stories we want. And that is it for the lesson.

    [05:35 - 05:47] I hope you enjoyed, and you can use this knowledge to basically create your own little add-ons for anything. Let's just say, for instance, you have translatable elements, and instead of the theme you want a language picker, you're free to do so.

    [05:48 - 05:59] And sometimes, you know, it's even better than installing add-ons for specific things, because this way, you create your own little add-on where you have full control of what you want to do with it. Anyways, I'll see you in the next lesson.