Next.jsにStorybookを入れて、Story上でページ遷移できるようにしたい

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

実際のコード(preview.tsx

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;

GitHubのREADME.md風のMarkdownを実装する

必要なライブラリを読み込む CDN

<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
  <!-- <script src="./marked.min.js"></script> -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@3.0.1/github-markdown.min.css">

これをhead タグの中に書く。

HTMLを書く

<textarea id="user_markdown" name="body">
<!-- 何か初期値入れるなら入れる -->
  </textarea>
  <div id="preview" class="markdown-body"></div>
  <button id="previewButton" type="button">プレビュー</button>

必要最低限書く。「class="markdown-body"」の中だけ、先程追加したスタイルが適応される。

JavaScript

<script>
    window.addEventListener('load', function() {
      // プレビューのイベント追加
      let user_markdown = document.getElementById('user_markdown');
      document.getElementById('previewButton').addEventListener('click', function() {
        preview(user_markdown.value);
      });
    });
    
    // MarkdownをHTMLに変換
    function preview(markdown) {
      document.getElementById('preview').innerHTML = marked.parse(markdown);
    }
</script>

終了。後は試してみて。

参考

※1 markedjs/marked https://github.com/markedjs/marked

※2 Markdown記法 チートシート https://gist.github.com/mignonstyle/083c9e1651d7734f84c99b8cf49d57fa

※3 Github Markdown CSSを使用する方法 https://webty.jp/staffblog/production/post-1840/

Unity メモ(1)

Unity オブジェクト・コンポーネント取得

昨年からプログラミングをC言語から学び始めて、4月からUnityを触り始めました。

以前から作りたかった簡単な照明のシミュレーターを作りながら思ったことを書いてみた。

GameObject.Find(string Name)

Nameに一致するオブジェクト名のオブジェクトを1つ取得。

戻り値 GameObject。

Nameに '/'を入れることで親オブジェクトから階層みたいにほることも可能。

 

例 GameObject 変数 = GameObject.Find("/親オブジェクト/子オブジェクト");

 


GameObject.Transform.Find(string Name)

Nameに一致する子オブジェクトを親オブジェクトのTransformから探し1つ取得。

戻り値 Transform(失敗時は null)。

 

例 Transform 変数 = 親オブジェクト.Transform.Find("子オブジェクト");

 

 

GameObject.FindGameObjectWithTag(string Name)

Nameに一致するタグを持つオブジェクトを1つ取得。

戻り値 GameObject(失敗時は null)。

例 GameObject 変数 = GameObject.FindGameObjectWithTag("タグ名");

 

 

FindObjectOfType<class>()
指定したクラス(GameObject)を1つ取得。

戻り値 (指定したクラス)(失敗時は null)。

あんまり使い道ないかも・・・。

 

GetComponent<class>()

指定したクラス(Component:Transform等)を1つ取得。

戻り値 (指定したクラス)(失敗時は null)。

GameObject.Find("オブジェクト").GetComponent<Component>();みたいに一気に探すことも可能。

 

例Component 変数 = GameObject.GetComponent<Component>();

 

※他にあれば追記してこうかな