I'm pretty new to Storybook. I am so frustrated I haven't used it in projects earlier as developing components in isolation is incredible. However I hit a bit of a gotcha this week when using it in my shadcn/ui based Next/Tailwind project.
If you want to use a custom font in Next app router you need to import them the next way to get the benefit of all Next's nextiness. If you're using Tailwind, the Next docs instruct you to export a variable name from the Next font object and insert it into the classNames
of the body element in your root layout. You then reference this variable in your tailwind config under sans
or your own chosen selector. This is also the instructions provided in the shadcn/ui Next setup docs. As someone who doesn't really use CSS variables this seems incredibly arkane, but it works fantastically well.
However, I noticed that it wasn't always working. I don't want to admit how long it took me to simply realising that when I was working in Storybook the font wasn't loading. In fact the only thing that flagged this issue was that it was falling back to a default sans-serif system font which didn't have a full range of font weights. Long story short, my fonts were not in Storybook.
Of course Storybook is NOT Next. The root layout where you are importing your font and defining its CSS variable isn't in use. Forehead slapping aside, the solution was relatively easy. In my case, I am using the shadcn/ui default font of Inter so I just needed to load this in and apply it to the body of the Storybook instance. And of course, you load this in, as per Google's advice, in the header of the document.
A little digging into the Storybook docs reveals a useful feature of preview-head.html
, which is a file you can define in your .storybook
directory which will then be treated as the head element of Storybook. This gives you somewhere to import your font from Google Font's CDN and also define a style tag where you apply the font to the body element. My file ended up looking like this:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
<style>
body {
font-family: "Inter", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
A previous attempt at solving this involved importing the font at Storybook's preview.tsx
in a global decorator, however this doesn't catch instances where components are instantiated as siblings of your story, such as with popovers or alert dialogs. A wrapper is almost as good, but using the preview head is more universal.
I hope this helps someone else in this confusing but not all that uncommon situation solve the problem a little faster than I did.
Top comments (1)
The distinction between Next.js and Storybook environments and the realization that the font loading issue was Storybook-specific is a valuable lesson. Your solution utilizing the preview-head.html in the .storybook directory, importing the font from Google Font's CDN, and defining the style tag to apply the font to the body element is a clever workaround.