Storybookの導入
npx storybook@latest init
Reactと変わらない ……がTypeScript入れているので、その辺りの記述の違いは見ておいた方がいいかも
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-onboarding",
"@storybook/addon-interactions",
],
framework: {
name: "@storybook/nextjs",
options: {},
},
docs: {
autodocs: "tag",
},
core: {
// <https://storybook.js.org/docs/configure/telemetry>
disableTelemetry: true, // telemetryの無効化追加
},
};
export default config;
一応おさらいとしてサーバーの起動の仕方は
npm run storybook
コマンドを打ち、http://localhost:6006/ にアクセス (Storybookは自動でブラウザ起動してくれるっぽいね)
React.jsで前、MemoryRouter使って、Storybook上でページ遷移できるようにしたし、Next.jsでもあったら便利かぁ~ と思って、調べていた
(っと軽はずみにはじめたら、後悔した……)
全然記事無くて、びびった~。 結局GitHub見に行って、かなり深い階層にあった~…… めちゅくちゃ彷徨った……. しかも、version7.0でも使えそうなのに、公式ドキュメント version8.0専用ページにあるし、どういうこっちゃ~?orz
まぁ何はともあれ、Next.jsでStorybook上でページ遷移をしたい場合、ここ参考にするといいと思う https://github.com/storybookjs/storybook/tree/next/code/frameworks/nextjs https://storybook.js.org/docs/8.0/get-started/nextjs
import type { Preview } from "@storybook/react";
import { action, HandlerFunction } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
type storybookPath = {
[key:string] : { title:string, story: string | undefined }
};
/**
* ページの設定
* 実際の「pathname」をキーに、ストーリーに変換するための変数
*/
const storybookPathes : storybookPath = {
'/Page': { title:'Example/Page', story:'Logged Out' },
};
/** 設定された内容を見て、ログをコンソールに出しつつ、実際にページ遷移する */
function switchLocal(pathname:string) {
console.log(pathname);
if(storybookPathes[pathname] != undefined) {
// // 用心深くいくならつけたらいいけど、入ることないはず
// if(storybookPathes[pathname].title == undefined) {
// console.log('error:param is wrong : ' + pathname);
// linkTo('Configure your project')();
// }
if(storybookPathes[pathname].story != undefined) {
console.log(`to ${storybookPathes[pathname].title} ${storybookPathes[pathname].story}`);
linkTo(storybookPathes[pathname].title, storybookPathes[pathname].story)();
} else {
console.log(`to ${storybookPathes[pathname].title}`);
linkTo(storybookPathes[pathname].title)();
}
} else {
console.log("This page has not yet been set up");
linkTo('Configure your project')();
}
}
type nextNavigationMethod = "push" | "replace" | "forward" | "back" | "prefetch" | "refresh"
function overridesMethod(
methodName:nextNavigationMethod,
args:any[]
):Promise<boolean> {
action(`nextRouter.${methodName}`)(...args);
if(args.length > 0 && typeof args[0] === "string") {
switchLocal(args[0]);
}
return Promise.resolve(true);
}
const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
nextjs: {
appDirectory: true, // App Router であることを設定する
navigation: { // next/navigation に対する設定
// それぞれのメソッドにフックする
push(...args) { return overridesMethod("push", args); },
replace(...args) { return overridesMethod("replace", args); },
forward(...args) { return overridesMethod("forward", args); },
back(...args) { return overridesMethod("back", args); },
prefetch(...args) { return overridesMethod("prefetch", args); },
refresh(...args) { return overridesMethod("refresh", args); },
},
},
},
};
export default preview;