本記事は Reactウィーク 4日目の記事です。
📍 3日目 ▶▶ 本記事 ▶▶ 5日目 📱
はじめに
はじめまして。インドア加速中で運動不足気味な、新卒入社4年目の西元です。
普段はフロントエンドエンジニアとして、業務アプリの開発・運用に携わっています。
今日はReactウィークということで、Reactプロジェクト向けのコンポーネントライブラリの開発経験をもとに、MUIのコンポーネントをEmotionでスタイリングする方法についてまとめます。
Next.jsの設定方法についても簡単に触れていますので、既存プロジェクトへの導入の際にも参考になればです。
(簡単に)MUI/Emotionとは
MUI
MUI(Material-UI)はReactコンポーネントライブラリです。
GoogleのMaterial Design(マテリアルデザイン)に基づいてデザインされたUIコンポーネントを提供しています。
Emotion
EmotionはJavaScriptでCSSを記述するためのライブラリです。
ReactをはじめとするJavaScript (TypeScript)ライブラリで、スタイリングに使用することができます。
開発環境の準備
Next.jsのプロジェクト作成
今回はNext.jsのプロジェクトにMUIとEmotionを導入して、コンポーネントをスタイリングしていきます。
まずは、Next.jsのプロジェクトを作成します。
インストール
以下のコマンドを実行して、Next.jsをインストールします。TypeScriptを使用したいので、オプションで指定しています。
npx create-next-app@latest --typescript
コマンドを実行すると設定について質問されるので、必要に応じて回答してください。
今回は以下のように設定しています。
これでNext.jsのプロジェクトが作成されました。
MUI/Emotionのインストール
インストール
続いて、以下のコマンドでMUIとEmotionをインストールします。
npm install @mui/material @emotion/react @emotion/styled
Next.jsの設定
Next.js(TypeScript)のプロジェクトでEmotionを使用するために、tsconfig.jsonに設定を追加します。
{ "compilerOptions": { "jsxImportSource": "@emotion/react", // JSX Pragmaを設定 "types": ["@emotion/react/types/css-prop"], // Emotionの型定義ファイルを設定 } }
これで設定は完了です。
オリジナルアコーディオンコンポーネントを作成する
今回は、MUIのAccordionを元に、オリジナルのアコーディオンコンポーネントを作成していきます。
1.自作コンポーネントを定義する
まずは、MUIのコンポーネントをラップして、自作コンポーネント(以降、CustomAccordion)を作成します。
MUIのアコーディオンは本来、3つのコンポーネント(Accordion/AccordionSummary/AccordionDetails)で構成されていますが、CustomAccordionではこれらを1つのコンポーネントにまとめます。
さらに、AccordionSummary、AccordionDetailsに設定する内容は外から渡せるように、propsを設定します。
CustomAccordion.tsx
import { Accordion, AccordionDetails, AccordionSummary } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { ReactNode } from "react"; export type CustomAccordionProps = { summaryContent: ReactNode; detailContent: ReactNode; }; export const CustomAccordion = ({summaryContent, detailContent}: CustomAccordionProps) => ( <Accordion> <AccordionSummary expandIcon={<ExpandMoreIcon />}> {summaryContent} </AccordionSummary> <AccordionDetails>{detailContent}</AccordionDetails> </Accordion> );
コンポーネントを呼び出す側のファイル
<CustomAccordion summaryContent={'Accordion 1'} detailContent={'アコーディオン1のコンテンツです。'} /> <CustomAccordion summaryContent={'Accordion 2'} detailContent={'アコーディオン2のコンテンツです。'} />
CustomAccordion(MUIのデフォルトスタイル)
2.MUIのCSSクラスを確認する
次に、MUIのコンポーネントをスタイリングするための準備を行います。
MUIには各コンポーネントの機能に関する情報がAPIリファレンスドキュメントにまとめられており、使用方法や設定可能なPropsについて記載されています。
例えば、Accordionに関しては以下のページを参照してください。
mui.com
デフォルトのCSSを上書きする場合は、CSS classesの項を参照し、スタイリングしたい箇所に適用されているCSSクラスを確認します。
3.EmotionでMUIのデフォルトCSSを上書きする
いよいよ、MUIのコンポーネントのスタイルを上書きしてスタイリングしていきます。
Emotionのスタイル記法
props経由でスタイルを渡す場合は、css propsを使用します。スタイル記法は、ストリングスタイルとオブジェクトスタイルの2種類があります。
TypeScriptのプロジェクトの場合、Emotionがオブジェクトスタイルを推奨しています。
詳しくは以下を参照してください。
emotion.sh
自作コンポーネントをスタイリングする
今回は、#20B2AA
をベースカラーにしたスタイルを適用し、最小幅を指定できるようにpropsを追加します。
スタイルの上書きについては、MUIのCSSクラスを指定し、スタイルを設定していくだけで問題ありません。
ただ、CSSクラスの指定だけではスタイルが上書きできない場合は、親セレクタを参照するなどしてCSSの詳細度を調整してください。
また、cssを関数として定義し、propsを引数として動的な値でスタイルを変更することもできます。
今回はprops minWidth
に設定された値をminWidthプロパティに設定することで、動的に最小幅を指定できるようにしています。
CustomAccordion.tsx
import { Accordion, AccordionDetails, AccordionSummary } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { ReactNode } from "react"; import { css } from '@emotion/react' export type CustomAccordionProps = { summaryContent: ReactNode; detailContent: ReactNode; minWidth?: string, // 新しく追加したprops }; export const CustomAccordion = ({ summaryContent, detailContent, minWidth = '500px' }: CustomAccordionProps) => ( <Accordion css={styles.accordion(minWidth)} > // minWidthに設定された値を引数としてセット <AccordionSummary expandIcon={<ExpandMoreIcon />} css={styles.summary}> {summaryContent} </AccordionSummary> <AccordionDetails css={styles.detail}>{detailContent}</AccordionDetails> </Accordion> ); const styles = { accordion: (minWidth: CustomAccordionProps['minWidth']) => css({ minWidth: minWidth, // propsから渡ってきた値をcssの値として適用 }), summary: css({ '&.MuiAccordionSummary-root ': { // 親セレクタを参照 backgroundColor: '#20B2AA', borderTop: 'solid 2px #20B2AA', }, '.MuiAccordionSummary-content': { color: '#FFF', fontWeight: 'bold' }, '.MuiAccordionSummary-expandIconWrapper': { color: '#FFF', } }), detail: css({ '&.MuiAccordionDetails-root' : { backgroundColor: `rgba(32, 178, 170, 0.1)`, border: 'solid 2px #20B2AA', padding: '32px' } }) }
コンポーネントを呼び出す側のファイル
<CustomAccordion summaryContent={'Accordion 1'} detailContent={'アコーディオン1のコンテンツです。'} minWidth={'700px'} /> <CustomAccordion summaryContent={'Accordion 2'} detailContent={'アコーディオン2のコンテンツです。'} minWidth={'700px'}/>
CustomAccordion(Emotionを使ってスタイリング)
これで、MUIのコンポーネントをEmotionでスタイリングしたCustomAccordionの完成です。
おわりに
今回はMUIのコンポーネントをEmotionでスタイリングする方法をご紹介しました。
MUIとEmotionを合わせることで、カスタマイズ性が高まり、柔軟なコンポーネント開発が可能になります。
ぜひ、MUIとEmotionを使って、自分好みのReactコンポーネントを作成してみてください。