Configuring Next.js, Typescript, Tailwind & Storybook

July 25, 2022

Programs Used:

  • React 18.1
  • NextJS 12.1.6
  • Tailwind 3.0.24
  • Typescript 4.7.3
  • Storybook 6.5.7

The Configuration

In your terminal, add next-js and typescript.

npx create-next-app@latest --typescript <project-name></project-name>

Change the directory.

cd <project-name>

Add Tailwind, PostCSS, and Autoprefixer.

npm install tailwindcss@latest postcss@latest autoprefixer@latest

Initialize Tailwind and PostCSS. (The “-p” creates a postCSS config file.)

npx tailwindcss init -p

Add an “.nvmrc” file to your project. Open the file and add your version number of node (example “14.17.6”).

14.17.6

Open tailwind.config.js and set content like this:


module.exports = {
content: [
"./pages/**/*.{ts,tsx}"
],
theme: {
extend: {},
},
plugins: [],
}

Open “styles/global.css” and add Tailwind.


@tailwind base;
@tailwind components;
@tailwind utilities;

Add Sass.

npm install --save-dev sass

Add Storybook.

npx sb init --builder webpack5

Reference the Tailwind CSS file and configure NextJS. Open “.storybook/preview.js” and import globals.css and NextJS configuration:


// .storybook/preview.js
import "../styles/globals.css";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}

import * as NextImage from "next/image";

const OriginalNextImage = NextImage.default;

Object.defineProperty(NextImage, "default", {
configurable: true,
value: (props) => typeof props.src === 'string' ? (
<OriginalNextImage {...props} unoptimized blurDataURL={props.src} />
) : (
<OriginalNextImage {...props} unoptimized />
),
});

Object.defineProperty(NextImage, "__esModule", {
configurable: true,
value: true
});

Update the tailwind.config.js  file.Storybook adds a “stories” directory in your project. Add a reference to it in the config like this:


module.exports = {
content: [
"./pages/**/*.{ts,tsx}",
"./stories/**/*.{ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}

Configure Storybook for postcss. Open “.storybook/main.js” and change code like this:

module.exports = {
"stories": [
"../stories/**/*.stories.mdx",
"../stories/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
// Add PostCSS into addons for compiling tailwind below
{
name: '@storybook/addon-postcss',
options: {
postcssLoaderOptions: {
implementation: require('postcss'),
},
},
},
// End PostCSS
],
"framework": "@storybook/react",
"core": {
"builder": "@storybook/builder-webpack5"
}
}

Add the @storybook/addon-postcss.

npm install --save-dev @storybook/addon-postcss

Now you’ll be able to add Tailwind styles to your Storybook components. Test by changing the “stories/Button.tsx” file to include a tailwind style like this (example “bg-yellow-500”).


import React from 'react';
import './button.css';

interface ButtonProps {
/**
* Is this the principal call to action on the page?
*/
primary?: boolean;
/**
* What background color to use
*/
backgroundColor?: string;
/**
* How large should the button be?
*/
size?: 'small' | 'medium' | 'large';
/**
* Button contents
*/
label: string;
/**
* Optional click handler
*/
onClick?: () => void;
}

/**
* Primary UI component for user interaction
*/
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
...props
}: ButtonProps) => {
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
return (
<button type="button" className={['bg-yellow-500', `storybook-button--${size}`].join(' ')}
style={{ backgroundColor }}
{...props}
>
{label}
</button>>
);
};

You should see the button background change to yellow after you run Storybook. Run Storybook:

npm run storybook