StorybookのColorPaletteの機能を使ってDesignTokenをドキュメント化する

Storybookに定義したTokenをドキュメントとして残せないか…と考えた時にStorybookにはColorPaletteという機能があるのを知りました。

ColorPaletteの機能を使ってドキュメントを作る方法について紹介します！

## ColorPaletteってなに？
公式のドキュメントに書かれているので概要はそちらから把握いただいた方が正確だと思います！

https://storybook.js.org/docs/react/api/doc-block-colorpalette

利用方法はColorPaletteを利用するファイルに`ColorPalette`と`ColorItem`をimportします！
ファイル拡張子は`**.stories.mdx`です。

```javascript
import { Meta, ColorPalette, ColorItem } from "@storybook/addon-docs/blocks";

// ページのタイトルを表記できます。h1でレンダリングされます
<Meta title="Colors" />
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/1d65d658-14a8-7723-1999-d0a285cf095f.png)

## 実装方法
`<ColorPalette>`で`<ColorItem>`をラップします。
公式サイトで表示されている例だと

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/ab720a00-d324-09af-91cb-683e31ffdfbf.png)
> [ColorPalette](https://storybook.js.org/docs/api/doc-block-colorpalette)

```javascript
<ColorPalette>
  <ColorItem
    title="theme.color.primary"
    subtitle="Coral"
    color={{ primary: '#FF4785'}}
  />
</ColorPalette>
```

titleとsubtitleはNameの下に表示されることになります。
Swatchesの下に表示されるのがcolorに渡した`{ primary: '#FF4785'}`のオブジェクトが表示されます。

:::note info
オブジェクトが提供されるとき、キーは値の上に表示されるので、値の上に表示したくない場合はkeyを提供しない形式でcolorに値を渡すと良いです！
:::

## tailwind.configで定義したオブジェクトを利用したい
独自定義したものやtailwindが用意しているカラーコードを利用したい場合が多いと思います。
その場合はtailwind.configに定義したコードをMDX側で呼び込むだけです！

```javascript:tailwind.config
// tailwindのcolorを使いたい場合
import tailwindColors from 'tailwindcss/colors'
// TypeScriptの場合型のimportも忘れずに
import type { Config } from 'tailwindcss'

const colors2 = {
  white: '#fff',
  black: '#000',
}

const config: Config = {
  ...baseConfig,
  content: ["./src/**/*.tsx"],
  theme: {
    // 上書きする場合はここに記述
    extend: {
      // デフォルトはそのままに、拡張する場合はここに記述
      colors: colors2
    },
  },
}

```

:::note warn
extendさせるのか上書きするのかはその後カラーやテキストをどのように扱いたいかによるので十分に議論して指定方法を検討してください！
:::

```javascript
import tailwindConfig from './tailwind.config';

<ColorPalette>
  <ColorItem
    title="theme.color.primary"
    subtitle="Coral"
    color={{ primary: tailwindConfig.theme.extend.colors.white }}
  />
</ColorPalette>
```

### `map()`を利用して効率的にColorItemを生成する
`map()`が利用できるので下記のように記述することもできます！

```javascript
<ColorPalette>
  {Object.entries(tailwindConfig.theme.extend.colors.hoge).map(
    ([key, color]) => (
      <ColorItem key={key} title={key} colors={[color]} />
    )
  )}
</ColorPalette>
```

hogeで指定された中身は下記のようなObjectです。

```javascript
hoge: {
  DEFAULT: '#カラーコード',
  primary: '#カラーコード',
},
```

複数の値を受け渡すことで下記のような表現も可能です！

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/ab6da274-086a-ab66-6e44-839179f97d52.png)
> [ColorPalette](https://storybook.js.org/docs/api/doc-block-colorpalette)

### 計算や処理もできるし、スタイルもあてられる
`map()`が利用できると説明しましたが、そのほか計算はもちろん、`map()`関数内で分岐処理も可能です！

```javascript

// remをpx表記にしたい時にbaseのフォントサイズ16を掛け算する
{tailwindConfig.theme.fontSize['small'] * 16}px

// スタイルを調整したい時にインラインスタイルをあてる
<p style={{ fontSiza: '18px', lineHeight: '1.5' }}>

// keyやvalueを元にテキストの分岐処理する
{Object.entries(tailwindConfig.theme.extend.colors.hoge).map(
  ([key, color]) => (
    <p>
      {key === 'aaaa' ? 'sample text' : '-'}
    </p>
  )
)}

```

## まとめ
ColorPaletteを利用することでドキュメントをさらに充実させられます！

ただ、TailwindCSSを利用する場合すべてのdefaltの値をカラーパレットとして表示してしまうのは逆に見づらくなる可能性もあります。

どんな要素を表示させるのが良いのかはデザイナーと相談できると良いと思います。