これは何
- この記事の続きで、UXPin MergeをTypeScriptとともに導入するための記事です。
- 前回はStorybookのイニシャライズで自動生成されたコードをそのまま使っていましたが、今回はそれらをCSS Modules化します
CSS Modulesを使う準備
ライブラリのインストール
まずはこちらのコマンド。
yarn add -D @types/css-modules storybook-css-modules-preset
@types/css-modulesの説明
TypeScriptの環境でCSS Modulesを使うと、以下のようなエラーが出ます。
Cannot find module './foo.module.css' or its corresponding type declarations.
これを解消するためにインストールしています。
中身は実質これだけなので、自分でd.tsをどこかに用意しても良いんですが……笑
interface CSSModule {
    /**
     * Returns the specific selector from imported stylesheet as string.
     */
    [key: string]: string;
}
Storybookの準備の続き
storybook-css-modules-presetをインストールしただけでは駄目なので、.storybook/main.jsを以下のように編集します。
  module.exports = {
    "stories": [
      "../stories/**/*.stories.mdx",
      "../stories/**/*.stories.@(js|jsx|ts|tsx)"
    ],
    "addons": [
      "@storybook/addon-links",
-     "@storybook/addon-essentials"
+     "@storybook/addon-essentials",
+     "storybook-css-modules-preset"
    ]
  }
ライブラリを使わずmain.jsの中に以下のような記述をしても良いのですが、使う方が簡単なので今回は採用しています。
webpackFinal: (config) => {
  // webpackの設定
}
UXPinの準備
uxpin.webpack.config.jsを編集します。
  {
    test: /\.css$/,
    use: [
      {
        loader: 'style-loader',
      },
      {
        loader: 'css-loader',
        options: {
-         importLoaders: 2
+         importLoaders: 2,
+         modules: true
        },
      },
    ],
  },
css-loaderのmodulesをtrueにするだけでOK。
CSS Modulesの適用
あとはひたすら同じ作業なので、Button.tsxを例にして説明します。
CSSのimportをCSS Modulesの作法にならって変更。
- import './button.css';
+ import styles from './button.module.css';
classNameが単なる文字列として指定されている箇所をCSS Modulesの作法にならって変更。
- const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+ const mode = primary ? styles['storybook-button--primary'] : styles['storybook-button--secondary'];
ちなみに一般的にはstyles.fooの書式だと思いますが、今回のようにクラス名がケバブケースになっている場合はstyles.['foo-bar']とすることで回避可能です。
| OK | NG | 
|---|---|
|  |  | 
そもそもハイフンで繋がなければ良いじゃん……というのはごもっともですが、ときには使えるテクニックかもしれません。
あとはひたすら同じ作業を繰り返していけば完成です!
ちなみに
前回の記事ではuxpin.config.jsからしれっとPage.tsxを抜いていました。
module.exports = {
  components: {
    categories: [
      {
        name: 'General',
        include: [
          'stories/Button.tsx',
          'stories/Header.tsx'
          // StorybookのイニシャライズでPage.tsxも生成されているけど登録していない
        ]
      }
    ],
    webpackConfig: 'uxpin.webpack.config.js'
  },
  name: 'UXPin Merge + TypeScript + Storybook'
}
じつはpage.cssの中ではh2やpなどタグに対して直接スタイルを指定していたんですね。
そのためUXPinのGUIの画面のスタイルが崩れてしまいます。
その説明を前回の記事の時点でするのは話がややこしくなるな……と思って省略していました。
今回CSS Modulesを適用したのでPage.tsxを登録しても問題なく動きます。
