本記事は 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コンポーネントを作成してみてください。