2

Use Storybook with Tailwind in an Nx Workspace

 3 years ago
source link: https://blog.nrwl.io/use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Generate a new library to host our page UI components

We want to have a library where to host our UI components s.t. they can be easily shared within our Nx workspace. Obviously, in our simple example of a blog platform, right now we don’t really have other apps in our workspace. In many cases a Nx workspace starts like this, and then over time we add new applications, either because new projects start or even because we split up existing projects into multiple ones for a better scalability. Furthermore, having a shared UI library is a common scenario especially in larger real-world applications to encapsulate the corporate design components.

To generate a new library, simply refer to the @nrwl/react:lib generator:

npx nx g @nrwl/react:lib ui --directory=shared --style=css

Notice, by passing the --directory=shared, Nx generates the library into a subfolder libs/shared/ui. Grouping libraries into sub-folders helps to further structure them.

In addition to generating the library setup, the above command also pre-generates a component shared-ui.tsx for us. Since we won't use that one right now, we can that we can just remove it.

So what do we want to achieve? Currently, on my blog, I have a “collection page” that contains small tiles for each type of topic I’ve been writing on the site. It looks something like this:

1*Ni6ZoBzT3GwfvQXDm2Ovcw.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Example rendering of the Topic Button

We want to replicate that as a React component. So let’s create a new component named “topic-button”

npx nx g @nrwl/react:component topic-button --project=shared-ui --style=css

By providing --project we make sure it gets generated into our new shared/ui library. Confirm the question about exporting the component. We definitely want to do that as we plan to use it in our Next app's page.

Notice also the / is changed to - when providing the project. You can also always look up the workspace.json for the corresponding name of the project. Or use Nx Console and get a nice autocomplete 😀.

Add Storybook Support to our Shared UI Library

Let’s add Storybook support to our library, such that we can develop our components in isolation. Let’s use Nx Console this time. Activate the VSCode command palette and type “Nx: “

1*1FPVM1iJ730HNlQEYHEEcQ.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
VSCode command dropdown for Nx Console

Choose “Nx generate (ui)” and search for “@nrwl/react:storybook-configuration”.

1*cTOoYZU_PRJN3ks2tmli0Q.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Choosing @nrwl/react:storybook-configuration

Provide the shared-ui in the project name to make sure the Storybook configuration gets generated for our UI library. In addition, I like to group my storybook related e2e tests into a dedicated folder, which is why I specify storybook-e2e for the cypressDirectory.

1*IrhdF6vAV5usU5Pmj2hsWQ.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
VSCode Nx Console extension — Detail view for Storybook configuration

For those of you not using VSCode or simply preferring the CLI, here’s the generate command:

npx nx generate @nrwl/react:storybook-configuration --name=shared-ui --cypressDirectory=storybook-e2e

What we get is the following:

1*GJa6PwKLfno5_Ugluqti2w.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
  1. Storybook configured for our shared/ui library
  2. A workspace-level Storybook configuration. Such configuration is particularly handy if you want to apply some specific configuration to all of your Storybooks within the Nx workspace. The project-level storybook setup simply imports the global Webpack configuration (as well as Storybook Add-ons and more) and applies them to the project-level Storybook configuration.
  3. A new Storybook story was generated automatically for our topic-button.tsx component. Note, you can always again trigger this by invoking the stories generator in the very same fashion as we did for the Storybook configuration setup
  4. A Cypress-based e2e test including test files for our topic-button.stories.tsx. We're going to cover this in more detail in the next article of the series. So stay tuned!

Launch Storybook for our shared UI library

npx nx storybook shared-ui

This launches Storybook and you should see the pre-generated Topic Button React component is visualized.

1*dKnJz41iFKObHfgaQ11eeg.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Storybook rendering of the default generated React component

Setup Storybook to use Tailwind

By using the @nrwl/react/plugin/storybook preset in your configuration (which is automatically preconfigured by the Nx Storybook generator), you're already set up to use Tailwind.

We only need to actually create the tailwind.config.js and postcss.config.js within our shared/ui library.

cd libs/shared/ui
npx tailwindcss init -p
1*YC1LZcrcbvuilSfITbTLCg.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
File Structure of the Tailwind setup for the Storybook library

Adjust the tailwind.config.js similarly to what we did for the Next application:

Again, we’d want to extend from the root-level Tailwind configuration to make sure we get repository-wide settings (e.g. your corporate-wide Tailwind settings).

Similarly, we adjust the postcss.config.js

Finally, in order to leverage the Tailwind styles in all our Storybook stories, let’s create a new tailwind-imports.cssin libs/shared/ui/.storybook

/* libs/shared/ui/.storybook/tailwind-imports.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

Once we have that file, we can import it into our preview.js file

// libs/shared/ui/.storybook/preview.js
import './tailwind-imports.css';

With that, we should be set up!

Creating our Topic Button React Component

Without going too much into the details, here’s what the content of the button would look like.

A quick explanation of what this component does:

  • It renders the Topic button mentioned previously
  • The SVG icons are placed directly at the same level as the topic-button.tsx in the shared/ui/src/lib/topic-button folder.
  • Based on the passed topicName, a similar SVG is searched and dynamically imported (see the useEffect logic. As a result each topic will have its corresponding SVG icon displayed.

You can find the icons here.

Developing our Storybook story

Nx automatically generates a Storybook story for your React components when you create the initial Storybook configuration for the library.

You can also re-run it afterwards:

nx g @nrwl/react:stories shared-ui

Let’s use that pre-generated setup and implement our story:

A couple of things to notice here:

  • I wrap the TopicButton component in a div and set the background color to make shadows etc more evident. Our main site would probably also have some background color, so ideally we would want to reuse that one here.
  • I setup a React state hook to record when we click the button and render that into our story. That makes it easy to see whether it worked or didn’t. Notice the default export also has an argTypes property, which logs the click output on the Storybook action panel. So you could also use that if you prefer to inspect the action result.

Running Storybook

If you now run the Storybook

npx nx storybook shared-ui

we see our Topic Button rendered properly, using TailwindCSS for the styling part.

1*ntBCwxL2ODG7fgQaWBCJMA.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Storybook rendering of the complete Topic Button with “Next.js” topicName

Changing topicName in the Storybook controls panel to “React” also changes the icon accordingly

1*GZ2BS3NkCx4zugzlqtAaJw.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Storybook rendering of the Topic Button with “React” topicName

Building Storybook

You can also build and deploy Storybook separately. This is especially interesting for documentation purposes, say when you’re building some shared UI components for your corporate design system.

To build Storybook run

npx nx build-storybook shared-ui

This creates a compiled bundle in dist/storybook/shared-ui which could be directly deployed to some static server. To test it, simply use a local http server and point it to the directory. For example:

npx http-server dist/storybook/shared-ui

Opening that in the browser would render Storybook just as it did during development mode:

1*UIGRI6ZXsx1ZL5ABSgx0Ug.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Building and running Storybook with a static webserver

Using our React Topic Button component in our Next.js app

Storybook is very neat for developing and documenting your components in isolation. But ultimately we want to use the component in our Next powered blog platform application.

Without building the full topic list page, let’s generate a “Topics page” in our Next app and use the newly TopicButton there.

First, we generate a new Next page:

npx nx generate @nrwl/next:page --name=topics --project=site

Next, let’s implement the page component:

Notice how we import the TopicButton.

Since Nx automatically maps libraries to paths in tsconfig.base.json, we can just import it from the local libs folder as if it was an npm package.

Finally launching the app properly renders the button on our Next app’s page:

1*sTjnTiKnWIxUKIpXP45VjA.png?q=20
use-storybook-with-tailwind-in-an-nx-workspace-5ceb08edad71
Using our React component developed with Storybook in the Next.js application

Note, you want to make sure to have svgr support enabled in your next.config.js in order to render SVGs properly.

Conclusion

In this article we learned

  • How to generate a new React library within our Nx workspace to host the shared UI components
  • How to add Storybook support to the React library
  • How to configure Storybook to support TailwindCSS
  • How to develop a React component in isolation with Storybook
  • How to use our shared React component in our Next.js application

GitHub repository
All the sources for this article can be found in this GitHub repository’s branch: https://github.com/juristr/blog-series-nextjs-nx/tree/07-storybook-tailwind


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK