Storybookの見た目をthemeを使ってカスタマイズする

:::note info
CSS-in-jsで使用できるthemingの機能ではなく、Storybook自体のサイドナビやパネルデザインのカスタマイズ紹介記事となります。
:::

Storybook公式のtheming APIを使用したカスタマイズを紹介します。


# 【準備】インストールするもの
カスタマイズに必要なパッケージをインストールします。
本記事の検証バージョンは`v7.6.4`です。
※Storybookはインストール済みとします。

```terminal
npm install --save-dev @storybook/manager-api @storybook/theming
```
# 【実践】いろいろ変えてみる

公式のリファレンスを見ながら色々設定してみます。
https://storybook.js.org/docs/configure/theming

:::note warn
以降カスタマイズの画面への反映はすべてStorybook再起動が必要です
:::

## ダークテーマを適用する

デフォルトではライトテーマとなっていますが、Storybookではダークテーマも用意されています。

![Storybookへダークテーマを適用した状態のキャプチャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633909/97bdab6f-e9af-6638-42fe-8aba78fe979f.png)

`.storybook/manager.ts`を作成し、以下のように記述します。

```typescript:.storybook/manager.ts
import { addons } from '@storybook/manager-api';
import { themes } from '@storybook/theming';

addons.setConfig({
  theme: themes.dark,
});
```

ちなみに、Docsは独立しているらしく上記の設定だけではテーマは切り替わらないため、Docsへもダークテーマを適用したい場合は、`preview.ts`へ記述を追加します。

```typescript:.storybook/preview.ts
import { Preview } from '@storybook/your-framework';

import { themes } from '@storybook/theming';

const preview: Preview = {
  parameters: {
    docs: { // Docsのテーマ設定
      theme: themes.dark,
    },
  },
};

export default preview;
```

すると、Docsの見た目もダークテーマになります。

![StorybookのDocsにもダークテーマが適用されている状態のキャプチャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633909/2341b66c-12e0-7476-57de-fa0927078189.png)


## テーマを自分で作る

さらに、自作のテーマを使ってStorybookロゴ部分を他の画像にしたり、フォントやUIパーツの色を部分的に調整することができます。

たとえばこのように変えることができます。
設定と対応する箇所にラベルをつけています。
※サンプルではわかりやすくするため、大胆な配色、数値、色名での指定をしています。

![Storybookの見た目をカスタマイズした状態のキャプチャへ設定項目名を示した図解](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633909/67be4024-0654-9dc8-d5b0-b508d96fb40d.png)

```typescript:.storybook/CustomTheme.ts
import { create } from '@storybook/theming/create';

export default create({
  base: 'light',
  // フォント
  fontBase: '"Open Sans", sans-serif',
  fontCode: 'monospace',

  // 左上のStorybookのロゴが入っていたエリア
  brandTitle: 'My custom Storybook', // imgタグのalt属性に反映される
  brandUrl: 'https://example.com', // imgをクリックした場合の遷移先
  brandImage: 'https://placehold.jp/3d4070/ffffff/300x300.png', // 左上の画像
  brandTarget: '_self', // 遷移の仕方。aタグのtarget属性に反映される

  // カラー
  colorSecondary: 'lightsalmon',

  // UI
  appBg: 'mistyrose', // サイドナビ背景
  appContentBg: 'gold', // 下部のタブパネルエリア背景
  appPreviewBg: 'whitesmoke', // プレビューエリア背景
  appBorderColor: 'white', // ボーダーカラー
  appBorderRadius: 20, // 角丸

  // テキストカラー
  textColor: 'black',
  textInverseColor: 'white',

  // ツールバー（下部のタブパネル）
  barTextColor: 'darkblue', // タブタイトルテキスト
  barSelectedColor: 'seagreen', // 選択中のタブ
  barHoverColor: 'orange', // タブホバー中の下線
  barBg: 'skyblue', // タブバーの背景

  // フォームカラー
  inputBg: 'lightsalmon', // input背景
  inputBorder: 'purple', // inputボーダー
  inputTextColor: 'salmon', // inputテキスト
  inputBorderRadius: 9999, // inputの角丸
});
```
自作したテーマは`manager.ts`で読み込みます。
```typescript:.storybook/manager.ts
import { addons } from '@storybook/manager-api';

import CustomTheme from "./CustomTheme";

addons.setConfig({
  theme: CustomTheme,
});
```
以上、紹介したものがすべての設定項目ではありませんが、カスタマイズしていくことで例えばUIカタログとしてStorybookを使う場合に、ブランドの世界観を表現することができるのではないかと思います。