Open16
Next13 x tailwind x storybook
Next.js v13(app dir) x tailwind 構成にstorybookを追加したい
- pnpm v8.6
storybook install
npx storybook@latest init
ここら辺が追加された
- storybookのパッケージ
- stories/
package.jsonに追加して起動すると、6006でアクセス可能
"dev:storybook": "storybook dev -p 6006",
tailwind対応
pnpm i @storybook/addon-styling -D
.storybook/main.ts
addons: [
// ...,
+ '@storybook/addon-styling',
]
実行
# Run the postinstall script from the root of your project
$ node node_modules/@storybook/addon-styling/bin/postinstall.js
=========================================
🧰 Configuring @storybook/addon-styling
=========================================
(1/3) Project summary
• Built with webpack
• Styled with tailwind
(2/3) .storybook/main.ts
• Registering @storybook/addon-styling.
(3/3) .storybook/preview.ts
• Adding import for withThemeByClassName decorator
• Adding import for stylesheet
• Adding withThemeByClassName decorator to config
✨ Done
code generator
手動で作るのは面倒なので避けたい。hygenしか知らなかったが、Plopが良いと聞いて使って見る。
pnpm i -D plop
plopfile.mjs
export default function (plop) {
plop.setGenerator('component', {
description: 'create a new component',
prompts: [
{
type: 'input',
name: 'path',
message: 'Where to create components? (e.g. components/atoms)',
},
{
type: 'input',
name: 'name',
message: 'What is the component name?',
},
],
actions: [
{
type: 'add',
path: '{{path}}/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/component/index.tsx.hbs',
skipIfExists: true,
},
{
type: 'add',
path: '{{path}}/{{pascalCase name}}/{{pascalCase name}}.test.tsx',
templateFile: 'plop-templates/component/component.test.tsx.hbs',
},
{
type: 'add',
path: '{{path}}/{{pascalCase name}}/{{pascalCase name}}.stories.tsx',
templateFile: 'plop-templates/component/component.stories.tsx.hbs',
},
],
})
}
hbsのsyntax highlight良いのないのか...
plop-templates/component/index.tsx.hbs
import { FC } from 'react'
type Props = {}
export const {{pascalCase name}}: FC<Props> = () => {
return (
<div>
{{pascalCase name}}
</div>
)
}
plop-templates/component/component.stories.tsx.hbs
import type { Meta, StoryObj } from "@storybook/react"
import { {{pascalCase name}} } from '.'
type T = typeof {{pascalCase name}}
export default {
component: {{pascalCase name}},
} satisfies Meta<T>
export const Default: StoryObj<T> = {}
plop-templates/component/component.test.tsx.hbs
import { render, screen } from "@testing-library/react"
import { {{pascalCase name}} } from "."
test('renders {{pascalCase name}} component', () => {
render(<{{pascalCase name}} />)
const titleElement = screen.getByRole( "heading", { level: 1, name: /{{pascalCase name}} Component/i })
expect(titleElement).toBeInTheDocument()
})
package.json
"scripts": {
...
"codegen": "plop component"
}
storybookのコンパイルエラー
- event compiled client and server successfully in 288 ms (20 modules)
- wait compiling...
- event compiled client and server successfully in 79 ms (20 modules)
WARN You (or an addon) are using the 'config' preset field. This has been replaced by 'previewAnnotations' and will be removed in 8.0
info Addon-docs: using MDX2
info => Using implicit CSS loaders
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
99% end closing watch compilationWARN Force closed preview build
ModuleNotFoundError: Module not found: Error: Can't resolve '../src/index.css'
.storybook/preview.tsでtailwindの読み込みができていなかった
.preview.ts
/* TODO: update import to your tailwind styles file. If you're using Angular, inject this through your angular.json config instead */
import '../index.css'
使っていないstories/を削除
.storybook/main.ts
- '../stories/**/*.mdx',
- '../stories/**/*.stories.@(js|jsx|ts|tsx)',
テストライブラリを追加
pnpm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
jest.config.mjs
import nextJest from 'next/jest.js'
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)
型がないと言われたので
pnpm i --save-dev @types/jest
package.json
"scripts": {
"test": "jest"
}
ついでに
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": ["--inspect-brk", "${workspaceRoot}/node_modules/jest/bin/jest.js", "--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}