ReactでTheme UI Part2

ReactでTheme UIを使用するチュートリアルのPart2です。

前回の記事では、ThemeUIを使用してページのレイアウトを定義しました。今回はMDXを使用してコンテンツ部分を作成し、更にスタイルを適用します。

デモを用意しようとしたのですが、Stackblizeだと記事本文とは異なるパッケージを利用しなければならないため、今回は割合しました💦

Create React App
Please note there’s a known bug with the macro so live reloading doesn’t currently work.
With Create React App you will need to use mdx.macro.

create-react-appにはバグがあり、mdx.macroを使用することになるためです。

内容は簡単なため、前回の完成品から手順通りにこなせば動作します。尚、Part1が動作していれば問題ないはずですが、WebpackとBabelがインストールされている必要があります。

MDX

MDXはmarkdownにjsxが利用できるフォーマットです。今回の例ではこのような利点は使用していませんが、markdownでは手の届かなかったコンテンツやメタ要素の組み込みが可能です。

React(Webpack)で使用するには、MDX用のローダーが必要になります。加えて、MDXで絵文字や画像が使用できるようにプラグインのインストールも行います。

## install Loader
yarn add @mdx-js/loader --dev

## Install Plugin
yarn add remark-emoji remark-images

次に、Webpackの設定ファイルにローダーの設定を行います。

const images = require('remark-images')
const emoji = require('remark-emoji')

module.exports = {
  module: {
    rules: [
      // ...(略)
      {
        test: /\.mdx?$/,
        use: [
          {
            loader: 'babel-loader'
          },
          {
            loader: '@mdx-js/loader',
            options: {
              remarkPlugins: [images, emoji]
            }
          }
        ]
      }
    ]
  }
}

言語プリセットをインストールします。

yarn add @babel/preset-env @babel/preset-react --dev

.babelrcに以下を追加します。

{
  "presets": [
    "@babel/env",
    "@babel/react"
  ]
}

これでプロジェクト上でMDXが利用できます。src/posts/first.mdxを作ってみましょう。

# Project1

Hello World!

上記をHTMLにコンバートして埋め込むには、インポートするだけです。


// src/components/Layout.js(抜粋)

import First from "../posts/first.mdx";

...

const Layout = ({ children }) => (
  <Main>
    <Container bg="muted" p={4}>
      <First />
    </Container>
  </Main>
);

MDXファイルに適用されるスタイルは、前回作成したテーマオブジェクトのstylesがマッピングされます。

export default {
  ...
  styles: {
		...
    h1: {
      color: 'text',
      fontFamily: 'heading',
      lineHeight: 'heading',
      fontWeight: 'heading',
      fontSize: 5,
    },
    ...
  }
}

実行結果

結果

Prism

ここまででMDXをHTMLにコンバートして、テーマオブジェクトのスタイルを適用することができました。最後にシンタックスハイライトを導入します。これを1番簡単に行うことができるのはPrismです。


yarn add @theme-ui/prism

ThemeProvidercomponent propを追加し、Prismを組み込んだコンポーネント指定します。


// App.js
import Prism from '@theme-ui/prism';

const components = {
  pre: ({ children }) => <>{children}</>,
  code: Prism,
};

const App = () => (
  <ThemeProvider theme={theme} components={components}>
    <Styled.root>
      <Global />
      <Layout />
    </Styled.root>
  </ThemeProvider>
);

あとはどのようなテーマで描画するかです。@theme-ui/prismにはあらかじめ複数のテーマが用意されているため、これをテーマオブジェクトに読み込ませてstyles.codeに指定します。

今回は、draculaというテーマを使用しました。


// theme.js
import dracula from '@theme-ui/prism/presets/dracula.json';

exports default = {
    styles: {
        code: {
        ...dracula,      
        }
    }
}

各自、first.mdxをcodeが含まれる内容に任意変更しておいてください。

上記の動画のように、絵文字や画像を利用することもできます。これらは最初にプラグインをインストールしたため、MDX上で取り扱うことが可能になっています。

Conclusion

MDXとPrismを使いページ本文を生成し、スタイルを適用しました。今回の例では触れませんでしたが、MDX内にReactで作成したチャートなども埋め込むこともできて便利です。

2回に分けて解説しましたが、Theme UIでページレイアウトをする方法が伝われば幸いです。