dev-resources.site
for different kinds of informations.
Integrating Storybook into an existing next.js project
In this article, you'll learn how to integrate Storybook into an existing Next.js project, including support for different themes.
Introduction
Storybook is an open-source tool that allows developers to build, test, and document UI components in isolation.
Install storybook
To get started, initialize Storybook in your project:
npx storybook@latest init
Configure Your Project
Below is an example configuration for integrating Storybook with a Next.js project:
main.ts
// main.ts
import type { StorybookConfig } from '@storybook/nextjs'
import { join, dirname } from 'path'
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, 'package.json')))
}
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
getAbsolutePath('@storybook/addon-onboarding'),
getAbsolutePath('@storybook/addon-essentials'),
getAbsolutePath('@chromatic-com/storybook'),
getAbsolutePath('@storybook/addon-interactions'),
],
framework: {
name: '@storybook/nextjs',
options: {},
},
staticDirs: ['../public'],
}
export default config
preview.ts
// preview.ts
import { Preview } from '@storybook/react'
import { themesNames } from '../src/theme'
// Contexts providers
import { withThemeProvider } from './themeProvider'
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime'
export const globalTypes = {
parameters: {
nextRouter: {
Provider: RouterContext.Provider,
},
},
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'defaultTheme',
toolbar: {
icon: 'paintbrush',
items: themesNames,
showName: true,
},
}
}
const preview: Preview = {
decorators: [withThemeProvider],
}
export default preview
Note: When configuring Storybook with custom providers, such as themes or global contexts, it’s essential to mock these contexts properly.
Context Providers Setup
themeProvider.tsx
// themeProvider.tsx
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { Decorator } from '@storybook/react'
import { QueryClient, QueryClientProvider } from 'react-query'
import { AppRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime'
import { GlobalStyle } from '../src/styles/Global.styles'
const queryClient = new QueryClient()
const themes = {
// ... all project themes
// 'projectName' : { ...settings}
}
// Contexts providers
export const withThemeProvider: Decorator = (Story, context) => {
const selectedTheme = context.globals.theme ?? 'defaultTheme'
return (
<QueryClientProvider client={queryClient}>
<AppRouterContext.Provider
// Overriding nextjs router functions
value={{
push: async () => true,
replace: async () => true,
back: () => {},
prefetch: async () => {},
forward: () => {},
refresh: () => {},
}}
>
<ThemeProvider theme={themes[selectedTheme]}>
<GlobalStyle />
<Story />
</ThemeProvider>
</AppRouterContext.Provider>
</QueryClientProvider>
)
}
Example: Button Component
1. Create the Component
Create a new folder for the component at /src/components/button. Inside this folder, add the following file:
/src/components/button/index.tsx
// index.tsx
export default function Button({children, onClick, disabled}){
return <button onClick={onClick} disabled={disabled}>{children}</button>
}
2. Add Stories
In the same folder, create a file named Button.stories.ts to define the stories for the Button component.
You can use diferents files [js|jsx|mjs|ts|tsx].
/src/components/button/Button.stories.ts
// Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react'
import { fn } from '@storybook/test'
import Button from './'
const meta = {
title: 'UI/Primary Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {},
args: { onClick: fn() },
} satisfies Meta<typeof Button>
export default meta
type Story = StoryObj<typeof meta>
export const Primary: Story = {
args: {
children: 'Button',
disabled: false,
},
parameters: {
nextjs: {
appDirectory: true,
},
},
}
export const Disabled: Story = {
args: {
children: 'Button Disabled',
disabled: true,
},
parameters: {
nextjs: {
appDirectory: true,
},
},
}
Run and Build Storybook
To build and run your Storybook environment, use the following commands:
Build Storybook:
npm run build-storybook
Run Storybook:
npm run storybook
Finally, you can view Storybook's UI by opening it in your browser. After running npm run storybook, Storybook will be accessible at:
http://localhost:6006
This interface allows you to browse, test, and document your components interactively. Enjoy exploring your UI components with Storybook! 🎉
Featured ones: