908: Storybook Has Evolved W/ Jeppe Reinhold

## Metadata
- Author: [[Syntax - Tasty Web Development Treats]]
- Full Title: 908: Storybook Has Evolved W/ Jeppe Reinhold
- Category: #podcasts
- URL: https://share.snipd.com/episode/b7e1e2c3-0f86-4a69-9ec1-e51e1b86296b
## Document Notes
## Highlights
- **Storybook's Core Purpose**
- Storybook allows developers to build and test UI components in complete isolation from the main app.
- It serves three main purposes: development, documentation, and testing of components.
Transcript:
Scott Tolinski
And for anyone who hasn't heard of Storybook yet, probably most of our audience has, can you give us a quick rundown of what it is and why you might want to use it?
Jeppe Reinhold
Right. So Storybook is, we call it a workshop for your front end. So essentially, if you're building your website or your UI, you would probably use components. And Storybook allows you to work with these components in isolation. So you don't have to look at them in the app, but like as a pure component. Storybook has three pillars. It's development, documentation, and testing. So you can choose to use Storybook however you want, just for developing on your components. Or you can use it to document. Maybe you have a design system where you write a lot of docs for every single component. Or also for testing, which I guess we're going to go more into today, where you write tests for your components, not for your full application.
Scott Tolinski
Oh, interesting. ([Time 0:01:40](https://share.snipd.com/snip/144c3769-0ebd-4a85-b1ad-87d71ef91ede))
- **Building Site Fully with Storybook**
- Wes Bos started building a new site using Storybook from the ground up, focusing on component isolation.
- This method encouraged designing components with clear inputs and outputs, making them more robust and less tightly coupled.
Transcript:
Wes Bos
I found it's been very helpful for us in in this process because i i personally have used storybook in the past but i never like built something in storybook really and so we're building This new site and i'm building it in storybook first and foremost and the thing that I've noticed first and foremost that it's helped with is like component design, the inputs and the Outputs of specific components and what a component needs to function independently makes it a little bit more robust than when you're building it so kind of tightly coupled to its Parent or children or anything.
Jeppe Reinhold
So Storybook really helps you in playing around with your component, very easily change up the props. How does that affect my component? Or getting the component into a specific state that would be really hard to get into in the application. That's a common problem with developing in the application first. ([Time 0:03:49](https://share.snipd.com/snip/5eb13c5a-cdc1-4363-8712-255871dc5a78))
- **Storybook Bundle Size Reduction**
- Storybook's bundling was historically bloated with large dependencies and many packages.
- Storybook 9 drastically reduces bundle size by replacing big packages like Express with smaller ones like Polka and consolidating core packages.
Transcript:
Scott Tolinski
Yeah, significantly smaller and like less nested, right?
Jeppe Reinhold
It's been a long time complaint of Storybook users that Storybook is bloated. Like that word bloat has just been over and over again repeated. And so with the rise of the E18E community, that's like, how can we make stuff smaller and faster? What is that community?
Scott Tolinski
The E18E?
Jeppe Reinhold
E18E? E18E. I can't even remember what it is. Oh, E18E.
Scott Tolinski
E18E.dev. Ecosystem Performance. Oh, that's a new one I've not seen before.
Jeppe Reinhold
Because it's like accessibility is a11y so ecosystem performance is e18e cool it's a community of some really smart people that are transforming the javascript ecosystem by building Smaller packages and replacing packages and they kick-started our journey towards reducing this bloat. We had some great contributions. And then finally, we said, OK, we're going to do this officially. And so we sort of split it into two parts. We called it actual bloat and perceived bloat. And the actual bloat is what you have reacted to, is the fact that Storybook had a lot of transitive dependencies, like hundreds and hundreds. And it also had a huge install size, like hundreds of megabytes. And so we replaced a lot of dependencies. So the biggest one was Express. That was by far the biggest part of that tree. We replaced that with Polka, which is like way smaller, has two dependencies. Yeah, I know Polka. And then we removed some dependencies because like, you know, some of the Lodash utilities, you can just do them in plain JavaScript today. You couldn't do that five years ago, but now you can. Okay. And then we pre-bundled a lot of dependencies also. That's a more advanced topic, but essentially some of the dependencies were huge when you pulled them in. But if we bundled them into Storybook and we only used a tiny part of it, we would lose hundreds of magnitude of size from that.
Scott Tolinski
I joked about that. I was like, Scott said, yeah, I don't know how they did it. And I was like, they're probably just bundling it before they ship it, you know? Instead of the alternative is shipping a package JSON, right, in the npm tree all the way down. But in your case, you're simply pre-bundling some of them because you only need a little sip of one of these packages here and there?
Jeppe Reinhold
Right. Wow. Yeah, and so it's not what we do for all of them at all. We did remove a lot of them, but some of them needed to be bundled in. And that has its own trade-offs, of course, but for us, we thought it was the best trade-off. So that was the actual bloat of the megabytes and the dependency tree, which makes it faster download Storybook also because you don't have to download a ton of dependencies. And then we tackled the perceived bloat in Storybook 9, which is when you initialize a new Storybook project, we would historically, we would add 15 packages, I think, to a package station. We was like the main Storybook and then the five add-ons and then the integration and then the svelte integration and all that. And that was annoying to everyone. So we ditched some of the add-ons and said they aren't used anymore. Add-on links is one of the add-ons to storebook that nobody uses. We moved a lot of them into core because we saw that, all right, 95% of users are using this add-on. We should just put it into the core package so you don't have to worry about that. And then I think we cut that in half. So now you only get four packages, I think, in your packages. And I can't remember. Yeah. So those two things, what we did to reduce the bloat of storebook, there's still more to do. And we are still collaborating with that ecosystem performance community. ([Time 0:07:09](https://share.snipd.com/snip/54a32d9d-7233-49b0-a5d2-be223fafcc78))
- **Writing Effective Stories**
- Write stories using the component story format where you define meta and export variants with different args.
- Each story represents a specific state or usage scenario of the component to test and document effectively.
Transcript:
Scott Tolinski
But how do you write a story? How do you decide what all the different props are to a component in all the different states?
Jeppe Reinhold
So a stories file is what we call, it has a format that we call component story format, CSF for short. And it all starts with a default export of the meta information, where you say, this is the component, and these are the default props I would like to pass into this component. In storebook, we call them arcs, but you could consider them props. And then you can do a lot more meta information. And then after that, you do one export per story. So you would, for your button component, you would export primary. And then for that story, there would be an object where you put in args primary equals true, or you can change the label with another type of prop. And then you just define a lot of exports each story is like a scenario of how this component could be represented. Okay. For Svelte, we have a special Svelte syntax called Svelte CSF, Svelte Component Story Format, where it's slightly different, but it's way more intuitive for a Svelte user because You write it in Svelte syntax. Okay. But still the same idea.
Scott Tolinski
Okay. So you just basically, you import the component, and then you try to think of every possible combination of that component. You know, a red one, a green one, a big one, a small one, et cetera, et cetera. Obviously, much more complex than a button, but a button is a really nice, simple example. And then how does that play into testing?
Jeppe Reinhold
So for each story, what you can do is you can define a play function. And that's essentially a function that runs after your story has rendered. So let's say you have a story for a form. Then that play function can contain interactions and assertions. Similar to if you've ever written tests with testing library in VTest or Jest, where you have element get by role or expect this to be in document. That's the exact same API we're giving you. In this play function, you write in, ([Time 0:20:04](https://share.snipd.com/snip/f0da36d5-66a6-42f3-94c0-ee36b8f55bcd))
- **Visual Interaction Testing Benefits**
- Writing tests as interactions on component stories helps catch UI bugs with visual feedback during test execution.
- This step-by-step visual approach makes debugging easier than reviewing terminal-only test results.
Transcript:
Jeppe Reinhold
This function to have been called because it actually submitted successfully. And you can define these play functions for each story, essentially. Yeah. And so it's a bit hard to explain the visual stuff. But what you'll see inside the storybook is that you'll see everything you did in the play function as a separate step. And you can actually step through it. So you can say, so if there's something unexpected happened, why didn't this error show? You can step to the specific input label filling out form and then oh it filled out the wrong thing or you can step to the next step and then and then still interact with component and then
Wes Bos
Step further on yeah if you've ever used store or um in that story have you ever used uh uh cypress or something like that it's not like the same concept because that's running it in a headless Bra do whatever but like it because that's usually running your whole site. It does give you that same sort of development workflow to be able to really truly understand, like, why is your test failing? Is it the test? Or is it the component itself? Again, like for me, I'm a visual guy, and we're writing components that are very visual. I found that to be a nice, than having just my test pass or fail in a terminal somewhere, right? ([Time 0:22:30](https://share.snipd.com/snip/8044ff7a-6732-4684-afbc-c00848df9b83))
- **Component-Level Visual Testing Value**
- Visual regression testing at the component level is less flaky and more precise than end-to-end or page-level tests.
- It detects small UI changes early to prevent slow accumulation of visual inconsistencies over time.
Transcript:
Jeppe Reinhold
And then behind the scenes, it takes a bunch of snapshots of each story. And then it sends the results back to your storybook. And then it shows you this is the diff between you took a snapshot maybe 10 days ago on the main branch, and this is a snapshot you're taking today. The button was clearly resized 10 pixels. And so we're sending it to the servers and then getting the results back. That's how it works behind the scenes.
Scott Tolinski
It makes sense to put the ([Time 0:25:35](https://share.snipd.com/snip/3d72b855-3b52-44d2-a1f8-9e0bad7a85ab))
- **Component Design for Testability**
- Split components into presentational and smart components to improve testability.
- Write stories for both components and even pages, mocking external data and services where needed.
Transcript:
Scott Tolinski
Talk about like best practices and and whatnot when you're when you're writing stories or building, even just like component design in general, I'm sure that bad component design Comes to you as I can't use storybook in this way. And the answer is often like, well, you shouldn't be doing it in that way. Are there any like bad practices or best practices that pop up when you're trying to design a component that is well tested and works well?
Jeppe Reinhold
I think what we've seen a lot is that when people, they have a big application with a lot of components and then they start to add Storybook in it. And as you say, they'll do oh, how do I ever write a story for this component? That must be because Storybook sucks. But then, well, you need to refactor your component to be testable, similar to how you would do unit tests, right? And one of the biggest things we tell people is do the presentational component versus a smart component split. It's an old way. We haven't discussed this in like five years or something, but it's still a very good way to construct components, which is one component takes a lot of props and then shows all the styles And then a parent component that do all the logic. That makes it way easier to play around with the presentational component just by changing a bunch of props, but then also write the test for the behavior of the parent component, where You actually do the interaction. I think that's a huge win for testable components. One thing that we're seeing all of the successful teams doing is actually also write stories for the pages, which might not be logical, but in SvelteKit, in Next.js, in Remix, your page Is actually also a component that just takes in a few cool props that you can do whatever you want. So you can write a story for your page and then navigate through that, but it's still not end-to because you still don't have the database, you don't have the network requests to your Auth provider and stuff. You're just mocking all that out. So it's just the UI still, even though it's a page. ([Time 0:29:59](https://share.snipd.com/snip/3e950c77-ddeb-435b-9210-9775f28a49c3))
- **Automate Accessibility Checks**
- Use Storybook’s accessibility add-on to catch component-level accessibility violations during development.
- Combine automated accessibility checks in Storybook with manual QA for thorough coverage.
Transcript:
Wes Bos
And I typically do most of my accessibility testing by hand in polypane. It's like, let's load it up in polypane. Let's do it once over on the site. I am enticed by the idea that you could be getting some accessibility help while you're actually developing. Can you tell me a little bit about what's going on with accessibility and what the features do here? Sure. So we have an accessibility add-on.
Jeppe Reinhold
And when you add that, what it does is that when the story is done rendering and when the play function is done playing, so you've done all your interactions, then it will use X core, the X package, to say, are there any accessibility violations here? You can configure it however you want to, like with different levels and different rules. But essentially, it will show you the violations. You don't have the correct color contrast here, or this heading is the wrong level. And then it will also highlight it in the UI. So you'll get a little square on top of the element that is violating, which makes it a lot easier to reason about. But of course, it's only on the component level, so it doesn't tell you if it works in the actual site with the tab index and the heading level might be off. So it's like an easy win to get a lot of violation reported to you per component because they're easy to fix on a component level, but you don't get the full test that you would get if you Manually did accessibility testing on your site. ([Time 0:35:19](https://share.snipd.com/snip/4f5bd040-7214-4a15-9b02-373c035ae6e0))
- **Leverage Useful Add-ons**
- Use add-ons like theme switcher to test components under different themes and pseudo-states.
- Utilize the new recording add-on to capture interactions as play functions without manual coding.
Transcript:
Jeppe Reinhold
Any theme that you define. You can define 10 themes. Really? You can define a billion themes in the theme switcher. Oh, I love that. I make themes. You just define what it should do when you change it, and then your component will react to that. There's a new add-on that I'm super excited about by a contributor called Igor. He just came out of nowhere and built this, and it's incredible. It allows you to record your interactions and save them as play functions. So you don't have to write the assertions. You don't have to write the interactions. You just press record, and you click around, and then you press save. And then it saves the play function to the story file.
Wes Bos
I'm glad that exists. Yeah, that's something that Cypress had that I really liked. I was going to ask about that, so I'm glad to hear that.
Jeppe Reinhold
So for Svelte, it doesn't work with saving to the file, but you can still copy-paste it into the file. That's fine. There's also a pseudo-states add-on, which allows you to force pseudo-states on your CSS. So you can say, now I want this button to be hovered. Oh, okay. And then what does that look like? Which is pretty hard to do because there's no browser API to do that today. Yeah, but it does some magic behind the scenes. ([Time 0:41:34](https://share.snipd.com/snip/e365688b-e6d0-4c6a-8399-2747cbb04c21))
- **Jeppe's Favorite Speaker**
- Jeppe Reinhold shared his favorite speaker: a JBL Boombox 3 with Wi-Fi and Bluetooth.
- It works well indoors with Wi-Fi casting and outdoors via Bluetooth, fitting his family's lifestyle.
Transcript:
Scott Tolinski
It's a parties it's a j Wi-Fi.
Jeppe Reinhold
And the reason I brought this on is because it both has Wi-Fi and Bluetooth, which is fantastic in my world, because when we're at home and then the kids will say, can you put on an audio Book? I'll just do the Chromecast thing or the Spotify Cast 2. And that just works with the Wi-Fi part. It doesn't take over my phone. I can still do calls. I can still do whatever, right? But then I live on a pretty big property, and we do a lot of work in the woods and stuff. And when we go outside for a full day of work, we just bring the speaker with us and then use the Bluetooth functionality instead. And it's just fantastic. I love that it has both. They also have a smaller version called Charge, I think.
Wes Bos
Yeah, the Wi-Fi connection for sound is way more reliable and less annoying than Bluetooth. I love being able to say, on Spotify, just play this on a kitchen speaker. Yeah, Bluetooth's the worst for that type ([Time 0:47:21](https://share.snipd.com/snip/faf624ee-46db-40b8-a6e7-1b61eadd2fdf))