はい、承知いたしました。Material UIの導入方法から主要コンポーネントの詳細な説明、そしてスタイルやテーマのカスタマイズ方法まで、約5000語で解説する詳細な記事を作成します。
【完全入門】Material UIの導入方法と主要コンポーネント
はじめに
モダンなWebアプリケーション開発において、UI(ユーザーインターフェース)の構築は非常に重要な要素です。ユーザーにとって使いやすく、見た目にも美しいインターフェースは、アプリケーションの成功に直結します。しかし、ゼロから高品質なUIコンポーネントを作成するのは、多くの時間と労力を要します。
そこで役立つのが、UIコンポーネントライブラリです。数あるライブラリの中でも、特に人気が高く、広く利用されているのが Material UI です。Material UIは、Googleが提唱するデザインシステム Material Design をReactコンポーネントとして実装したライブラリで、洗練されたデザインと豊富な機能を提供します。
Material UIとは?
Material UIは、Reactに特化したUIコンポーネントライブラリです。Googleが開発・提唱しているデザインシステム「Material Design」の原則に基づいたコンポーネントを提供します。Material Designは、物理世界とその法則(紙とインクのメタファーなど)をデジタルインターフェースに取り入れたもので、直感的で一貫性のあるユーザー体験を提供することを目的としています。
Material UIを使うことで、開発者はデザインに関する深い知識がなくても、プロフェッショナルでモダンなUIを簡単に構築できます。提供されるコンポーネントは、レスポンシブデザインに対応しており、アクセシビリティにも配慮されています。
なぜMaterial UIを使うのか?
- デザインの一貫性: Material Designに基づいたコンポーネント群は、アプリケーション全体に統一感のあるデザインをもたらします。
- 開発効率の向上: ボタン、入力フォーム、ダイアログ、ナビゲーションなど、一般的なUI要素があらかじめ用意されているため、ゼロから作成する手間が省け、開発速度が大幅に向上します。
- カスタマイズ性: 用意されているコンポーネントは、テーマシステムやスタイルシステムを通じて高度にカスタマイズ可能です。プロジェクトのブランドイメージに合わせて色やフォント、形状などを自由に変更できます。
- アクセシビリティ: Material UIのコンポーネントは、WAI-ARIA(Web Accessibility Initiative – Accessible Rich Internet Applications)のガイドラインを考慮して設計されており、キーボードナビゲーションやスクリーンリーダーへの対応が進んでいます。
- 豊富なコンポーネント: レイアウトから複雑なデータ表示まで、幅広い用途に対応できる多様なコンポーネントが用意されています。
- コミュニティ: 非常に多くの開発者に利用されており、活発なコミュニティがあります。問題が発生した際にも、解決策を見つけやすいです。
この記事で学べること
この記事では、Material UIの基本的な使い方を網羅的に解説します。具体的には、以下の内容を学ぶことができます。
- Material UIプロジェクトへの導入方法
- Material Designの基本概念とMaterial UIにおけるその適用方法
- コンポーネントのスタイリングとテーマの適用方法
- 主要なUIコンポーネントの詳細な使い方 (レイアウト、フォーム、データ表示、フィードバックなど)
- より高度なスタイリングとテーマのカスタマイズ方法
ReactでのUI開発を効率化したい方、Material Designに興味がある方にとって、この記事がMaterial UI活用の強力な一歩となることを願っています。
それでは、早速Material UIの世界に入り込みましょう!
第1章: Material UIの導入
Material UIを使い始めるための最初のステップは、プロジェクトへのインストールと基本的な設定です。ここでは、ReactプロジェクトにMaterial UIを導入する方法をステップごとに解説します。
1. 環境構築
Material UIはReactライブラリなので、React開発ができる環境が必要です。以下のものが準備されていることを確認してください。
- Node.js: JavaScriptの実行環境。npm (Node Package Manager) が含まれています。推奨バージョンは公式ドキュメントを確認してください。
- npm または yarn: パッケージ管理ツール。どちらかがあればOKです。
まだNode.jsがインストールされていない場合は、公式ウェブサイトからインストーラーをダウンロードしてインストールしてください。
2. プロジェクトの作成
Material UIを導入するReactプロジェクトが必要です。ここでは、一般的なプロジェクト作成方法としてCreate React App (CRA) とNext.jsを例に挙げますが、どちらか一方、あるいは既存のプロジェクトでも構いません。
Create React App (CRA) で新しいプロジェクトを作成する場合:
bash
npx create-react-app my-material-ui-app
cd my-material-ui-app
Next.js で新しいプロジェクトを作成する場合:
bash
npx create-next-app my-material-ui-app --typescript --eslint --app # または --pages
cd my-material-ui-app
プロジェクトディレクトリに移動したら、次のステップに進みます。
3. Material UIのインストール
プロジェクトにMaterial UIをインストールします。コアライブラリと、スタイルを管理するためのライブラリ(EmotionまたはStyled Components)が必要です。Material UI v5以降では、Emotionがデフォルトのスタイルエンジンとして推奨されていますが、Styled Componentsも利用可能です。ここではEmotionをインストールする例を示します。
npmを使う場合:
bash
npm install @mui/material @emotion/react @emotion/styled
yarnを使う場合:
bash
yarn add @mui/material @emotion/react @emotion/styled
これでMaterial UIのコアパッケージと、スタイルを適用するための基盤となるパッケージがインストールされました。
4. フォントの設定 (Roboto)
Material Designでは、デフォルトのフォントとして Roboto が推奨されています。Material UIのコンポーネントもRobotoを前提としたデザインになっているため、導入することを強く推奨します。導入方法はいくつかありますが、最も簡単なのはCDNを利用する方法です。
public/index.html
ファイルを開き、<head>
タグ内に以下の <link>
タグを追加します。
html
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
より厳密にパフォーマンスを管理したい場合は、フォントファイルをダウンロードしてプロジェクトに含めるか、fontsource
のようなライブラリを利用する方法もあります。
例: fontsource
を使用する場合
“`bash
npm
npm install @fontsource/roboto
yarn
yarn add @fontsource/roboto
“`
次に、アプリケーションのエントリーポイント(例: src/index.js
や src/pages/_app.js
(Next.js))でインポートします。
“`javascript
// src/index.js (CRAの場合)
import ‘@fontsource/roboto/300.css’;
import ‘@fontsource/roboto/400.css’;
import ‘@fontsource/roboto/500.css’;
import ‘@fontsource/roboto/700.css’;
// その他のインポート…
import React from ‘react’;
import ReactDOM from ‘react-dom/client’;
import ‘./index.css’; // デフォルトのCSSがあれば
import App from ‘./App’;
const root = ReactDOM.createRoot(document.getElementById(‘root’));
root.render(
);
“`
5. アイコンの設定 (Material Icons)
Material UIでは、Material Designのガイドラインに沿ったアイコンセット Material Icons を簡単に利用できます。これもフォントと同様に、CDNまたはnpmパッケージで導入できます。
CDNを利用する方法:
public/index.html
の <head>
タグ内に以下の <link>
タグを追加します。
html
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
npmパッケージを利用する方法:
“`bash
npm
npm install @mui/icons-material
yarn
yarn add @mui/icons-material
“`
npmパッケージでインストールした場合、各アイコンは個別にインポートして使用します。
“`javascript
import AccessAlarmIcon from ‘@mui/icons-material/AccessAlarm’;
import ThreeDRotation from ‘@mui/icons-material/ThreeDRotation’;
function MyComponent() {
return (
);
}
“`
通常はnpmパッケージでの利用が推奨されます。必要なアイコンだけをバンドルに含めることができるため、パフォーマンス上有利です。
6. ThemeProvider
の導入
アプリケーション全体でMaterial UIのテーマ(色、タイポグラフィ、間隔など)を適用するために、アプリケーションのルートコンポーネントを ThemeProvider
でラップすることが推奨されます。ThemeProvider
は@mui/material/styles
からインポートします。
“`javascript
// src/index.js (CRAの場合) または src/pages/_app.js (Next.jsの場合)
import React from ‘react’;
import ReactDOM from ‘react-dom/client’; // CRAの場合
import App from ‘./App’;
import { ThemeProvider, createTheme } from ‘@mui/material/styles’;
import CssBaseline from ‘@mui/material/CssBaseline’; // CSSリセットのため
import ‘@fontsource/roboto/300.css’; // フォントのインポート(npmの場合)
import ‘@fontsource/roboto/400.css’;
import ‘@fontsource/roboto/500.css’;
import ‘@fontsource/roboto/700.css’;
// デフォルトテーマを作成
const defaultTheme = createTheme();
// CRAの場合
const root = ReactDOM.createRoot(document.getElementById(‘root’));
root.render(
{/ CssBaselineでCSSのリセットを適用 /}
);
// Next.jsの場合 (pages/_app.js)
/*
import type { AppProps } from ‘next/app’;
import { ThemeProvider, createTheme } from ‘@mui/material/styles’;
import CssBaseline from ‘@mui/material/CssBaseline’;
import ‘@fontsource/roboto/300.css’;
import ‘@fontsource/roboto/400.css’;
import ‘@fontsource/roboto/500.css’;
import ‘@fontsource/roboto/700.css’;
const defaultTheme = createTheme();
function MyApp({ Component, pageProps }: AppProps) {
return (
);
}
export default MyApp;
*/
“`
createTheme()
は、Material Designのデフォルトテーマオブジェクトを生成します。ThemeProvider
にこのテーマオブジェクトを渡すことで、アプリケーション内のMaterial UIコンポーネント全てにこのテーマが適用されます。
CssBaseline
は、ブラウザ間のCSSの差異を正規化するためのコンポーネントです。多くの場合は導入することをおすすめします。
7. 初期設定の確認
導入が成功したか確認するために、簡単なMaterial UIコンポーネントを表示してみましょう。src/App.js
を編集します。
“`javascript
import React from ‘react’;
import Button from ‘@mui/material/Button’; // Buttonコンポーネントをインポート
import Typography from ‘@mui/material/Typography’; // Typographyコンポーネントをインポート
import Box from ‘@mui/material/Box’; // Boxコンポーネントをインポート
function App() {
return (
// BoxはCSSユーティリティとして余白や配置を簡単に設定できます
Material UIへようこそ!
);
}
export default App;
“`
プロジェクトを起動してブラウザで確認します。
“`bash
npm
npm start
yarn
yarn start
“`
デフォルトのRobotoフォントが適用され、青い背景色のボタンが表示されていれば、Material UIの基本的な導入は成功です!
第2章: Material UIの基本概念
Material UIを効果的に使うためには、その基盤となっているMaterial Designの考え方や、Material UI独自のスタイルシステム、テーマシステムといった基本概念を理解することが重要です。
1. Material Designとは?
Material Designは、Googleによって開発された視覚、モーション、インタラクションデザインのための総合的なデザインシステムです。以下の原則に基づいています。
- Material is the Metaphor: 物理的な世界(紙とインク)のメタファーを用いて、デジタルインターフェースに質感や奥行き、動きを与えます。要素はレイヤーを持ち、影や重力、物理的な法則に従うかのように振る舞います。
- Bold, Graphic, Intentional: 大胆でグラフィックなデザインを重視し、意味のある配置や色彩、タイポグラフィを用いて情報を効果的に伝えます。
- Meaningful Motion: アニメーションやトランジションは単なる装飾ではなく、ユーザーの注意を引き、状態の変化を伝え、操作に対するフィードバックを提供するために利用されます。
Material UIは、これらの原則をReactコンポーネントとして忠実に再現することを目指しています。
2. コンポーネントの種類
Material UIは非常に多くのコンポーネントを提供しており、これらは機能や用途に応じて分類されています。主なカテゴリには以下のようなものがあります。
- Layout: ページ全体の構造や要素の配置を決定するためのコンポーネント(
Box
,Container
,Grid
,Stack
など)。 - Inputs: ユーザーからの入力を受け付けるためのコンポーネント(
Button
,TextField
,Checkbox
,Radio
,Select
,Slider
など)。 - Data Display: 情報を表示するためのコンポーネント(
Typography
,Icon
,Avatar
,Badge
,Card
,Paper
,Table
など)。 - Feedback: ユーザーへのフィードバックや状態表示のためのコンポーネント(
Alert
,Snackbar
,Progress
,Dialog
,Skeleton
など)。 - Navigation: アプリケーション内を移動するためのコンポーネント(
AppBar
,Drawer
,Tabs
,Pagination
,Breadcrumbs
,Menu
など)。 - Utility: 他のコンポーネントや機能と組み合わせて使用するユーティリティコンポーネント(
Modal
,Popover
,Tooltip
,ClickAwayListener
など)。
これらのコンポーネント群を適切に組み合わせることで、複雑なUIも効率的に構築できます。
3. スタイルシステム
Material UIでは、コンポーネントの見た目(スタイル)をどのように定義・適用するかが重要な概念です。Material UI v5以降では、CSS-in-JSライブラリ(デフォルトはEmotion)を利用したモダンなスタイルシステムが推奨されています。主なスタイリング方法には以下の2つがあります。
a) sx
prop (最も推奨)
ほとんどのMaterial UIコンポーネントは sx
という特別なpropを持っています。この sx
propを使うと、コンポーネントに直接CSSのスタイルをオブジェクト形式で指定できます。これは一時的なスタイル変更や、簡単なカスタマイズに非常に便利です。
sx
propは、Material UIのテーマシステムと深く連携しています。たとえば、margin
や padding
の値にはテーマで定義された間隔(spacing)単位を使用でき、color
にはテーマの色パレットを指定できます。また、レスポンシブデザインのためのブレークポイントに基づいたスタイル変更も容易に行えます。
“`javascript
import Box from ‘@mui/material/Box’;
function MyComponent() {
return (
<Box
sx={{
width: 300, // ピクセル指定
height: 300,
backgroundColor: ‘primary.dark’, // テーマの色パレットを使用 (theme.palette.primary.dark)
‘&:hover’: { // 疑似要素/クラス
backgroundColor: ‘primary.main’,
opacity: [0.9, 0.8, 0.7], // レスポンシブな不透明度
},
m: 2, // margin: theme.spacing(2)
p: 1, // padding: theme.spacing(1)
display: ‘flex’,
justifyContent: ‘center’,
alignItems: ‘center’,
color: ‘white’,
fontWeight: ‘bold’,
// レスポンシブ対応 (ブレークポイントを使用)
// xs: 0px, sm: 600px, md: 900px, lg: 1200px, xl: 1536px デフォルト
width: {
xs: 100,
sm: 200,
md: 300,
},
}}
>
Styled Box
</Box>
);
}
“`
sx
propは非常に強力で柔軟なスタイリング方法であり、ほとんどのユースケースで利用できます。
b) styled()
helper
より複雑なカスタムコンポーネントを作成したり、既存のMaterial UIコンポーネントに大規模なスタイル変更を加えたい場合は、@mui/material/styles
から提供される styled()
helper関数を使用するのが適しています。これはEmotionやStyled Componentsの styled
関数と同様のAPIを提供します。
“`javascript
import Button from ‘@mui/material/Button’;
import { styled } from ‘@mui/material/styles’;
// Material UIのButtonコンポーネントを拡張してスタイルを適用
const CustomButton = styled(Button)(({ theme }) => ({
// デフォルトのボタンスタイルを上書き
backgroundColor: theme.palette.secondary.main,
color: theme.palette.common.white,
padding: theme.spacing(2, 4), // 上下2単位、左右4単位の間隔
border: ‘none’,
borderRadius: theme.shape.borderRadius * 2, // テーマのborderRadiusを使用
// ホバー時のスタイル
‘&:hover’: {
backgroundColor: theme.palette.secondary.dark,
},
}));
function MyComponent() {
return (
カスタムボタン
);
}
“`
styled()
helperは、テーマオブジェクトにアクセスできるコールバック関数を受け取り、その中でスタイルを定義します。これにより、テーマの値に基づいたスタイリングや、より複雑なCSS構造(ネストされたセレクタなど)の定義が可能になります。
古いAPI (makeStyles
, withStyles
)
Material UI v4以前では、@mui/styles
パッケージから提供される makeStyles
や withStyles
といったHooksやHigher-Order Components (HOC) が主に使われていました。これらはJSS (JavaScript Style Sheets) を使用していましたが、v5以降ではEmotionやStyled Componentsを推奨するため非推奨 (deprecated) となっています。新規プロジェクトでは sx
prop や styled()
helper を使用することを強く推奨します。
4. テーマ (Theming)
Material UIの最も強力な機能の一つがテーマシステムです。アプリケーション全体の色、タイポグラフィ、間隔、形状、ブレークポイントなどの視覚的な一貫性をテーマオブジェクトとして一元管理できます。
a) テーマオブジェクトの構造
テーマオブジェクトは、以下のような主要なプロパティを持ちます。
palette
: アプリケーションで使用する色のパレット。primary, secondary, error, warning, info, success といった主要な色や、grey, common (white, black) などが含まれます。各色には main, light, dark, contrastText などのバリエーションがあります。typography
: フォントファミリー、フォントサイズ、行間など、テキストに関するスタイルを定義します。h1, body1, button, caption など、様々なバリアント(種類)が定義されています。spacing
: 要素間の間隔を定義するための単位(デフォルトは8px)。theme.spacing(1)
は8px、theme.spacing(2)
は16px といったように計算されます。breakpoints
: レスポンシブデザインの基準となる画面幅(ブレークポイント)。デフォルトは xs, sm, md, lg, xl です。shape
: 角丸の度合い(borderRadius)。shadows
: 影のスタイル(elevation)。transitions
: アニメーションの定義。zIndex
: レイヤーの重なり順。components
: 個々のMaterial UIコンポーネントに対するデフォルトスタイルの上書きや、プロパティのデフォルト値を設定できます。
b) テーマのカスタマイズ方法
@mui/material/styles
から提供される createTheme()
関数を使って、デフォルトテーマを拡張または上書きすることでテーマをカスタマイズします。
“`javascript
import { createTheme } from ‘@mui/material/styles’;
const customTheme = createTheme({
palette: {
primary: {
main: ‘#1976d2’, // デフォルトのprimary色を上書き
light: ‘#42a5f5’,
dark: ‘#1565c0’,
contrastText: ‘#fff’,
},
secondary: {
main: ‘#9c27b0’, // secondary色を追加/上書き
},
error: {
main: ‘#d32f2f’,
},
// … その他の色
},
typography: {
fontFamily: [ // フォントファミリーの追加
‘-apple-system’,
‘BlinkMacSystemFont’,
‘”Segoe UI”‘,
‘Roboto’,
‘”Helvetica Neue”‘,
‘Arial’,
‘sans-serif’,
‘”Apple Color Emoji”‘,
‘”Segoe UI Emoji”‘,
‘”Segoe UI Symbol”‘,
].join(‘,’),
h1: { // h1タイポグラフィバリアントのカスタマイズ
fontSize: ‘3rem’,
fontWeight: 500,
},
// … その他のタイポグラフィ
},
spacing: 4, // 間隔単位をデフォルトの8pxから4pxに変更 (theme.spacing(1) => 4px)
shape: {
borderRadius: 8, // 角丸の度合いをデフォルトの4pxから8pxに変更
},
components: {
// Buttonコンポーネント全体のデフォルトスタイルを上書き
MuiButton: {
defaultProps: {
// デフォルトのvariantをcontainedにする
variant: ‘contained’,
// デフォルトの色をsecondaryにする
color: ‘secondary’,
},
styleOverrides: {
// rootクラス(Buttonの最上位要素)のスタイルを上書き
root: {
textTransform: ‘none’, // テキストを全て大文字にしない
},
// containedVariantクラスのスタイルを上書き
containedSecondary: {
boxShadow: ‘none’, // 影をなくす
},
},
},
// … その他のコンポーネント
},
});
“`
作成したカスタムテーマオブジェクトを ThemeProvider
に渡すことで、アプリケーション全体に反映させることができます。
“`javascript
import { ThemeProvider } from ‘@mui/material/styles’;
// … customThemeのインポート/定義
function App() {
return (
{/ アプリケーション全体 /}
);
}
“`
c) ネストされたテーマ
ThemeProvider
はネストすることができます。内側の ThemeProvider
は、外側のテーマを継承しつつ、自身のテーマで上書き・追加した部分のみを適用します。これにより、アプリケーションの一部だけ異なるテーマを適用するといったことが可能です。
d) ダークモードの実装
Material UIのテーマシステムを利用すると、ライトモードとダークモードの切り替えを比較的容易に実装できます。createTheme()
関数は、palette
の mode
プロパティに 'light'
または 'dark'
を指定することで、自動的にそれぞれのモードに適した色のパレットを生成します。
動的な切り替えには、ReactのStateやContext APIと組み合わせて、テーマオブジェクトを動的に生成し ThemeProvider
に渡す仕組みが必要です。
“`javascript
import React, { useState, useMemo } from ‘react’;
import { ThemeProvider, createTheme } from ‘@mui/material/styles’;
import CssBaseline from ‘@mui/material/CssBaseline’;
import Button from ‘@mui/material/Button’;
function App() {
const [mode, setMode] = useState<‘light’ | ‘dark’>(‘light’);
// modeが変更されるたびに新しいテーマオブジェクトを作成
const theme = useMemo(
() =>
createTheme({
palette: {
mode: mode, // ‘light’ または ‘dark’
// 必要に応じて個別の色もカスタマイズ可能
// primary: {
// main: mode === ‘light’ ? ‘#1976d2’ : ‘#90caf9’,
// },
},
// … その他のテーマ設定
}),
[mode], // modeが変更されたときだけ再生成
);
const toggleColorMode = () => {
setMode((prevMode) => (prevMode === ‘light’ ? ‘dark’ : ‘light’));
};
return (
{/ CssBaselineはモードに合わせて背景色などを調整します /}
現在のテーマ: {mode}
{/ 他のMaterial UIコンポーネント /}
);
}
“`
このように、createTheme
と palette.mode
を利用することで、簡単にダークモードに対応したアプリケーションを構築できます。
第3章: 主要コンポーネントの詳細な解説
Material UIには非常に多くのコンポーネントがありますが、ここでは特に使用頻度の高い主要なコンポーネントをピックアップし、それぞれの特徴と基本的な使い方をコード例と共に解説します。
1. レイアウト関連 (Layout)
ページの構造や要素の配置を担うコンポーネントです。
Box
Box
は、sx
prop を最大限に活用するための強力なコンポーネントです。CSSユーティリティとして機能し、HTMLの div
要素(あるいは component
propで指定した要素)に、テーマに基づいたスタイリングを簡単に適用できます。余白、色、タイポグラフィ、Flexbox、Gridなど、ほぼ全てのCSSプロパティを sx
prop で指定できます。
“`javascript
import Box from ‘@mui/material/Box’;
import Typography from ‘@mui/material/Typography’;
function BoxExample() {
return (
);
}
“`
sx
propは、spacing
, color
, typography
, breakpoints
などのテーマの値に短縮記法でアクセスできます。例えば、m
は margin
、p
は padding
、t
は top
、l
は left
などです。さらに、方向を指定する t
, b
, l
, r
, x
, y
や、レスポンシブブレークポイントを組み合わせることができます(例: pt={{ xs: 2, md: 4 }}
)。これは非常に便利で、インラインスタイルでは難しかったレスポンシブ対応やテーマとの連携を容易にします。
Container
コンテンツを中央に配置し、最大幅を制限するためのコンポーネントです。レスポンシブに対応しており、ブレークポイントごとに最大幅を調整できます。
“`javascript
import Container from ‘@mui/material/Container’;
import Typography from ‘@mui/material/Typography’;
function ContainerExample() {
return (
// maxWidth=’sm’ は、smブレークポイント (600px) までは100%、
// md以上のブレークポイントでは最大幅がsmの最大幅になることを意味します。
// デフォルトは ‘lg’ (1200px) です。falseを指定すると最大幅の制限がなくなります。
);
}
“`
Grid
レスポンシブなグリッドシステムを構築するためのコンポーネントです。Flexboxをベースにしており、12カラムシステムを採用しています。
“`javascript
import Grid from ‘@mui/material/Grid’;
import Paper from ‘@mui/material/Paper’; // グリッドアイテムを見やすくするためのPaper
function GridExample() {
return (
// container prop は Flexbox コンテナになります
{/ item prop は Flexbox アイテムになります /}
Grid Item 1
Grid Item 2
Grid Item 3
Grid Item 4 (md: 8カラム)
);
}
“`
Grid
コンポーネントは container
と item
の両方のpropを持つことができますが、一般的には container
と item
を分けて使用します。container
でグリッドの親要素を定義し、item
で各子要素のカラム幅や配置を定義します。
Stack
1次元(縦または横)のレイアウトを簡単に構築するためのコンポーネントです。Flexboxの機能を使って、子要素の間に一定の間隔を空けたり、配置を制御したりできます。
“`javascript
import Stack from ‘@mui/material/Stack’;
import Button from ‘@mui/material/Button’;
function StackExample() {
return (
// direction=’row’ は子要素を横に並べます(デフォルトは’column’)
// spacing={2} は子要素間にテーマのspacing単位で2単位の間隔を空けます
);
}
“`
Stack
は簡単なレイアウトには非常に便利ですが、複雑な2次元レイアウトには Grid
の方が適しています。
2. 入力関連 (Inputs)
ユーザーからの入力を受け付けるためのコンポーネントです。
Button
クリック可能なボタンを表示します。様々なバリアント、色、サイズ、アイコンなどを指定できます。
“`javascript
import Button from ‘@mui/material/Button’;
import DeleteIcon from ‘@mui/icons-material/Delete’;
import SendIcon from ‘@mui/icons-material/Send’;
function ButtonExample() {
return (
{/ デフォルト /}
{/ バリアント /}
{/ 色 /}
{/ サイズ /}
{/ 無効化 /}
{/ アイコン付き /}
}>
Delete
}>
Send
);
}
“`
variant
には 'text'
, 'contained'
, 'outlined'
があります。color
にはテーマで定義された 'primary'
, 'secondary'
, 'success'
, 'error'
, 'info'
, 'warning'
や 'inherit'
などが指定できます。
TextField
テキストを入力するためのフォームフィールドです。ラベル、プレースホルダー、エラー表示、ヘルパーテキストなど、豊富な機能を持ちます。
“`javascript
import TextField from ‘@mui/material/TextField’;
import Box from ‘@mui/material/Box’;
function TextFieldExample() {
return (
{/ Filled TextField /}
{/ Standard TextField /}
{/ ラベル、プレースホルダー、デフォルト値 /}
{/ タイプ指定 (例: password) /}
);
}
“`
variant
には 'outlined'
, 'filled'
, 'standard'
があります。label
, placeholder
, defaultValue
(または value
) など、多くの標準的なinput属性をpropsとして渡せます。error
propを渡すとエラー状態になり、helperText
でエラーメッセージを表示できます。InputProps
, InputLabelProps
, FormHelperTextProps
などのpropを使うと、内包されている要素(<input>
, <label>
, <p>
など)に直接propsを渡すことができます。
Checkbox
, Radio
, Switch
真偽値や複数の選択肢から一つを選択するためのコンポーネントです。通常は FormControl
, FormLabel
, FormGroup
, FormControlLabel
と組み合わせて使用し、アクセシビリティやグループ化を適切に行います。
“`javascript
import * as React from ‘react’;
import FormGroup from ‘@mui/material/FormGroup’;
import FormControlLabel from ‘@mui/material/FormControlLabel’;
import Checkbox from ‘@mui/material/Checkbox’;
import Radio from ‘@mui/material/Radio’;
import RadioGroup from ‘@mui/material/RadioGroup’;
import FormControl from ‘@mui/material/FormControl’;
import FormLabel from ‘@mui/material/FormLabel’;
import Switch from ‘@mui/material/Switch’;
function InputSelectionExample() {
const [checked, setChecked] = React.useState(true);
const [selectedValue, setSelectedValue] = React.useState(‘a’);
const handleCheckboxChange = (event: React.ChangeEvent
setChecked(event.target.checked);
};
const handleRadioChange = (event: React.ChangeEvent
setSelectedValue(event.target.value);
};
const handleSwitchChange = (event: React.ChangeEvent
// State更新ロジック (例としてCheckboxと同じにする)
setChecked(event.target.checked);
};
return (
{/ チェックボックス /}
label=”Controlled Checkbox”
/>
{/* ラジオボタン */}
<FormControl sx={{ mt: 2 }}>
<FormLabel id="demo-radio-buttons-group-label">Gender</FormLabel>
<RadioGroup
aria-labelledby="demo-radio-buttons-group-label"
defaultValue="female"
name="radio-buttons-group"
value={selectedValue}
onChange={handleRadioChange}
>
<FormControlLabel value="female" control={<Radio />} label="Female" />
<FormControlLabel value="male" control={<Radio />} label="Male" />
<FormControlLabel value="other" control={<Radio />} label="Other" />
</RadioGroup>
</FormControl>
{/* スイッチ */}
<FormControlLabel
control={<Switch checked={checked} onChange={handleSwitchChange} />}
label="Switch"
sx={{ display: 'block', mt: 2 }} // ブロック要素として表示
/>
</Box>
);
}
“`
FormControlLabel
は、入力コンポーネント (control
propで指定) とラベル (label
prop) を関連付け、クリック可能領域を広げるなどアクセシビリティを向上させます。RadioGroup
はラジオボタンをグループ化し、一つの選択肢のみが選択されるように管理します。
Select
ドロップダウンリストから値を選択するためのコンポーネントです。MenuItem
コンポーネントと組み合わせて使用します。
“`javascript
import * as React from ‘react’;
import Box from ‘@mui/material/Box’;
import InputLabel from ‘@mui/material/InputLabel’;
import MenuItem from ‘@mui/material/MenuItem’;
import FormControl from ‘@mui/material/FormControl’;
import Select, { SelectChangeEvent } from ‘@mui/material/Select’;
function SelectExample() {
const [age, setAge] = React.useState(”);
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
);
}
“`
FormControl
と InputLabel
を一緒に使うことで、ラベルとセレクトボックスが正しく関連付けられ、アクセシビリティが向上します。Select
コンポーネントは、TextField
と同様に variant
(outlined
, filled
, standard
) を持つことができます。
3. データ表示関連 (Data Display)
情報をユーザーに表示するためのコンポーネントです。
Typography
テキストを表示するためのコンポーネントです。Material Designのタイポグラフィスケール(h1〜h6, body1, body2など)に沿ってテキストスタイルを適用できます。
“`javascript
import Typography from ‘@mui/material/Typography’;
import Box from ‘@mui/material/Box’;
function TypographyExample() {
return (
{/ h1 見出しスタイル /}
h1 Heading
{/ h4 見出しスタイル、pタグとしてレンダリング /}
h4 Heading (as p)
{/ body1 本文スタイル /}
Body 1 text. This is a paragraph with body 1 style.
{/ body2 本文スタイル /}
Body 2 text. This is another paragraph with body 2 style.
{/ テキスト中央寄せと色 /}
Subtitle 1, centered, secondary color
);
}
“`
variant
propで適用したいタイポグラフィスタイルを指定します。component
propを使うと、実際にレンダリングされるHTML要素を指定できます(例: variant="h4"
で <p>
タグとして表示)。gutterBottom
propは、テキストの下に余白を追加します(段落の最後に便利です)。
Icon
Material IconsやカスタムSVGアイコンを表示するためのコンポーネントです。
“`javascript
import Icon from ‘@mui/material/Icon’; // Font Icons用
import AccessAlarmIcon from ‘@mui/icons-material/AccessAlarm’; // SVG Icons用
import ThreeDRotation from ‘@mui/icons-material/ThreeDRotation’;
function IconExample() {
return (
{/ Font Icons (CDNでMaterial Iconsを導入した場合) /}
{/* SVG Icons (npmパッケージで導入した場合) */}
<AccessAlarmIcon />
<AccessAlarmIcon color="secondary" />
<AccessAlarmIcon fontSize="large" />
<ThreeDRotation sx={{ color: 'error.main' }} />
</Box>
);
}
“`
Font Iconsを使用する場合は Icon
コンポーネントにアイコン名をテキストとして渡します。SVG Iconsを使用する場合は @mui/icons-material
からアイコンコンポーネントをインポートして使用します。SVGアイコンの方がバンドルサイズを最適化しやすく、推奨される方法です。
Avatar
ユーザーのプロフィール画像やイニシャルを表示するためのコンポーネントです。
“`javascript
import Avatar from ‘@mui/material/Avatar’;
import Stack from ‘@mui/material/Stack’;
function AvatarExample() {
return (
{/ 画像アバター /}
{/ イニシャルアバター /}
{/ アイコンアバター /}
{/ サイズ /}
);
}
“`
src
propで画像URLを指定するか、子要素としてテキストやアイコンを渡すことで表示内容を定義します。sx
propでサイズなどを調整できます。
Badge
アイコンやテキストなどの要素の右上に小さなバッジ(通知数など)を表示するためのコンポーネントです。
“`javascript
import * as React from ‘react’;
import Badge from ‘@mui/material/Badge’;
import MailIcon from ‘@mui/icons-material/Mail’;
import ShoppingCartIcon from ‘@mui/icons-material/ShoppingCart’;
import Box from ‘@mui/material/Box’;
function BadgeExample() {
return (
{/ 通知数付きバッジ /}
{/ 0を表示しない /}
{/ 点を表示 /}
{/ 最大値 /}
);
}
“`
badgeContent
propでバッジの内容(テキストや数字)を指定します。color
propでバッジの色を変更できます。variant="dot"
で中身のない点だけを表示することも可能です。max
propで表示する最大値を制限できます。
Card
関連性の高いコンテンツ(画像、テキスト、アクションなど)をまとめるためのコンポーネントです。
“`javascript
import * as React from ‘react’;
import Card from ‘@mui/material/Card’;
import CardActions from ‘@mui/material/CardActions’;
import CardContent from ‘@mui/material/CardContent’;
import CardMedia from ‘@mui/material/CardMedia’;
import Button from ‘@mui/material/Button’;
import Typography from ‘@mui/material/Typography’;
function CardExample() {
return (
{/ 画像エリア /}
{/ コンテンツエリア /}
Lizard
Lizards are a widespread group of squamate reptiles, with over 6,000
species, ranging across all continents except Antarctica
{/ アクションエリア /}
);
}
“`
Card
は、CardMedia
, CardContent
, CardActions
などのサブコンポーネントと組み合わせて使用するのが一般的です。これにより、カードの構造(メディア、内容、アクション)を明確に定義できます。
Paper
UI要素をまとめるための汎用的なコンテナです。物理的な紙のような概念を模しており、影(elevation)を付けて奥行きを表現できます。
“`javascript
import Paper from ‘@mui/material/Paper’;
import Typography from ‘@mui/material/Typography’;
function PaperExample() {
return (
{/ 影なし (elevation={0}) /}
{/ 標準的な影 (elevation={3}) /}
{/ より強い影 (elevation={8}) /}
);
}
“`
elevation
propで影の強さを指定します。値は0から24までの整数です。Paper
は、単純なコンテナとしてだけでなく、フォームやセクションを囲むためにも広く使われます。
Table
構造化されたデータを表形式で表示するためのコンポーネント群です。
“`javascript
import * as React from ‘react’;
import Table from ‘@mui/material/Table’;
import TableBody from ‘@mui/material/TableBody’;
import TableCell from ‘@mui/material/TableCell’;
import TableContainer from ‘@mui/material/TableContainer’;
import TableHead from ‘@mui/material/TableHead’;
import TableRow from ‘@mui/material/TableRow’;
import Paper from ‘@mui/material/Paper’;
function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData(‘Frozen yoghurt’, 159, 6.0, 24, 4.0),
createData(‘Ice cream sandwich’, 237, 9.0, 37, 4.3),
createData(‘Eclair’, 262, 16.0, 24, 6.0),
createData(‘Cupcake’, 305, 3.7, 67, 4.3),
createData(‘Gingerbread’, 356, 16.0, 49, 3.9),
];
function TableExample() {
return (
{/ aria-labelでアクセシビリティ向上 /}
{rows.map((row) => (
{row.name}
))}
);
}
“`
TableContainer
, Table
, TableHead
, TableBody
, TableRow
, TableCell
といった複数のコンポーネントを組み合わせて使用します。各コンポーネントにはテーブル構造に応じた適切なWAI-ARIA属性が設定されており、アクセシビリティにも配慮されています。
4. フィードバック関連 (Feedback)
ユーザーへの情報伝達やアプリケーションの状態表示を行うコンポーネントです。
Alert
警告、成功、情報などの重要なメッセージを表示するためのコンポーネントです。
“`javascript
import * as React from ‘react’;
import Alert from ‘@mui/material/Alert’;
import AlertTitle from ‘@mui/material/AlertTitle’;
import Stack from ‘@mui/material/Stack’;
import Button from ‘@mui/material/Button’;
import IconButton from ‘@mui/material/IconButton’;
import CloseIcon from ‘@mui/icons-material/Close’;
function AlertExample() {
const [open, setOpen] = React.useState(true);
return (
{/ シンプルなAlert /}
{/* タイトル付きAlert */}
<Alert severity="success">
<AlertTitle>Success</AlertTitle>
This is a success alert with an observing eye.
</Alert>
{/* アクション付きAlert */}
<Alert
severity="warning"
action={
<Button color="inherit" size="small">
UNDO
</Button>
}
>
This is a warning alert with an action.
</Alert>
{/* 閉じるボタン付きAlert */}
{open && (
<Alert
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
sx={{ mb: 2 }}
>
Closable alert.
</Alert>
)}
</Stack>
);
}
“`
severity
propでアラートの種類(error
, warning
, info
, success
)を指定し、色やアイコンが自動的に切り替わります。AlertTitle
サブコンポーネントでタイトルを追加できます。action
propには、ボタンなどの要素を渡してインタラクティブな要素を追加できます。
Snackbar
アプリケーションの下部に一時的なメッセージ(トースト通知)を表示するためのコンポーネントです。通常、一定時間後に自動的に消えます。
“`javascript
import * as React from ‘react’;
import Button from ‘@mui/material/Button’;
import Snackbar from ‘@mui/material/Snackbar’;
import Alert from ‘@mui/material/Alert’;
function SnackbarExample() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(true);
};
const handleClose = (event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === ‘clickaway’) { // 要素外クリックでは閉じないようにする(オプション)
return;
}
setOpen(false);
};
return (
{/ 通常はAlertコンポーネントを子要素として使うのが推奨 /}
ノートがアーカイブされました!
);
}
“`
open
propで表示状態を制御し、onClose
で閉じた時の処理を定義します。autoHideDuration
で自動的に閉じるまでの時間を設定できます。メッセージの表示には、直接 message
propを使うよりも、子要素として Alert
コンポーネントを使う方が、デザインや機能(アイコン、severityカラーなど)がリッチになります。
Progress
処理の進捗状況を示すコンポーネントです。線形(Linear)と円形(Circular)の2つのタイプがあります。
“`javascript
import * as React from ‘react’;
import CircularProgress from ‘@mui/material/CircularProgress’;
import LinearProgress from ‘@mui/material/LinearProgress’;
import Box from ‘@mui/material/Box’;
function ProgressExample() {
return (
{/ 円形プログレス (indeterminate – 不確定) /}
{/ 円形プログレス (determinate – 確定) /}
{/* 線形プログレス (indeterminate - 不確定) */}
<Box sx={{ width: '100%' }}>
<LinearProgress />
</Box>
{/* 線形プログレス (determinate - 確定) */}
<Box sx={{ width: '100%', mt: 2 }}>
<LinearProgress variant="determinate" value={50} />
</Box>
</Box>
);
}
“`
variant
propで 'indeterminate'
(進捗率不明)または 'determinate'
(進捗率確定)を指定します。determinate
の場合は value
propで進捗率(0〜100)を指定します。
Dialog
ユーザーの注意を引き、特定のタスクや情報に集中させるためのモーダルコンポーネントです。確認、情報の入力、詳細表示などに使用されます。
“`javascript
import * as React from ‘react’;
import Button from ‘@mui/material/Button’;
import Dialog from ‘@mui/material/Dialog’;
import DialogActions from ‘@mui/material/DialogActions’;
import DialogContent from ‘@mui/material/DialogContent’;
import DialogContentText from ‘@mui/material/DialogContentText’;
import DialogTitle from ‘@mui/material/DialogTitle’;
function DialogExample() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
);
}
“`
DialogTitle
, DialogContent
, DialogActions
といったサブコンポーネントでダイアログの各部分を構成します。open
propで表示状態を制御し、onClose
で閉じる処理を定義します。aria-labelledby
や aria-describedby
といったアクセシビリティ属性を適切に設定することが推奨されます。
5. ナビゲーション関連 (Navigation)
アプリケーション内の移動やセクションの切り替えを行うコンポーネントです。
AppBar
アプリケーションの最上部に配置されるヘッダーバーです。タイトル、ナビゲーション要素、アクションボタンなどを配置できます。
“`javascript
import * as React from ‘react’;
import AppBar from ‘@mui/material/AppBar’;
import Box from ‘@mui/material/Box’;
import Toolbar from ‘@mui/material/Toolbar’;
import Typography from ‘@mui/material/Typography’;
import Button from ‘@mui/material/Button’;
import IconButton from ‘@mui/material/IconButton’;
import MenuIcon from ‘@mui/icons-material/Menu’;
function AppBarExample() {
return (
MyApp Title
{/ AppBarがfixedなどの場合、コンテンツがAppBarの下に隠れないように余白が必要 /}
{/
{/
);
}
“`
position
propでバーの固定方法(static
, fixed
, sticky
など)を指定できます。Toolbar
は、AppBar内でコンテンツを横一列に配置するためのユーティリティコンポーネントです。
Drawer
画面の端からスライドして表示されるサイドバーです。ナビゲーションメニューなどに使用されます。
“`javascript
import * as React from ‘react’;
import Box from ‘@mui/material/Box’;
import Drawer from ‘@mui/material/Drawer’;
import Button from ‘@mui/material/Button’;
import List from ‘@mui/material/List’;
import Divider from ‘@mui/material/Divider’;
import ListItem from ‘@mui/material/ListItem’;
import ListItemButton from ‘@mui/material/ListItemButton’;
import ListItemIcon from ‘@mui/material/ListItemIcon’;
import ListItemText from ‘@mui/material/ListItemText’;
import InboxIcon from ‘@mui/icons-material/MoveToInbox’;
import MailIcon from ‘@mui/icons-material/Mail’;
function DrawerExample() {
const [open, setOpen] = React.useState(false);
const toggleDrawer =
(newOpen: boolean) =>
(event: React.KeyboardEvent | React.MouseEvent) => {
if (
event.type === ‘keydown’ &&
((event as React.KeyboardEvent).key === ‘Tab’ ||
(event as React.KeyboardEvent).key === ‘Shift’)
) {
return;
}
setOpen(newOpen);
};
const DrawerList = (
{[‘Inbox’, ‘Starred’, ‘Send email’, ‘Drafts’].map((text, index) => (
{index % 2 === 0 ?
))}
{[‘All mail’, ‘Trash’, ‘Spam’].map((text, index) => (
{index % 2 === 0 ?
))}
);
return (
{DrawerList} {/ ドロワー内のコンテンツ /}
);
}
“`
open
propで表示状態を制御し、onClose
で閉じる処理を定義します。子要素としてドロワー内に表示するコンテンツを渡します。anchor
propで表示される方向(left
, right
, top
, bottom
)を指定できます。一時的なドロワー(画面幅が狭い場合に表示されるもの)と、常駐するドロワーがあります。
Tabs
コンテンツセクションを切り替えるためのタブインターフェースです。
“`javascript
import * as React from ‘react’;
import Tabs from ‘@mui/material/Tabs’;
import Tab from ‘@mui/material/Tab’;
import Box from ‘@mui/material/Box’;
import Typography from ‘@mui/material/Typography’;
interface TabPanelProps {
children?: React.ReactNode;
index: number;
value: number;
}
// タブのコンテンツを表示するためのヘルパーコンポーネント
function CustomTabPanel(props: TabPanelProps) {
const { children, value, index, …other } = props;
return (
aria-labelledby={
simple-tab-${index}
} // アクセシビリティのための関連付け{…other}
>
{value === index && ( // 現在アクティブなタブの場合のみコンテンツを表示
)}
);
}
// タブとパネルを関連付けるためのヘルパー関数
function a11yProps(index: number) {
return {
id: simple-tab-${index}
,
‘aria-controls’: simple-tabpanel-${index}
,
};
}
function TabsExample() {
const [value, setValue] = React.useState(0); // 現在アクティブなタブのインデックス
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
};
return (
{/ タブパネル /}
Tab Content One
Tab Content Two
Tab Content Three
);
}
“`
Tabs
コンポーネントは、タブの選択状態 (value
prop) と、タブが変更されたときのイベント (onChange
prop) を管理します。子要素として Tab
コンポーネントを並べます。各 Tab
には label
や他のprops ({...a11yProps(index)}
) を設定します。タブに対応するコンテンツ領域(Tab Panel)は、通常はカスタムコンポーネントを作成し、現在の value
に応じて表示・非表示を切り替えるように実装します。
6. ユーティリティ関連 (Utility)
他のコンポーネントや機能と組み合わせて使用する、基盤となるコンポーネントです。
Tooltip
要素にカーソルを合わせたときやフォーカスしたときに、補足的なテキストを表示するコンポーネントです。
“`javascript
import * as React from ‘react’;
import Button from ‘@mui/material/Button’;
import Tooltip from ‘@mui/material/Tooltip’;
function TooltipExample() {
return (
);
}
“`
title
propにツールチップとして表示したいテキストを指定します。子要素として、ツールチップを表示させたい要素(通常はインタラクティブな要素)を渡します。placement
propでツールチップの表示位置(top
, bottom
, left
, right
など)を指定できます。
4. スタイルとテーマの応用
第2章で触れたスタイルシステムとテーマシステムについて、より具体的な応用例や詳細を掘り下げます。
1. sx
prop の詳細活用
sx
propは非常に柔軟で、様々なスタイリング要求に応えることができます。
-
テーマ値へのアクセス:
color
:color="primary.main"
(theme.palette.primary.main
)bgcolor
(backgroundColor):bgcolor="secondary.light"
(theme.palette.secondary.light
)m
,p
系の余白:m={2}
(theme.spacing(2)
),px={3}
(padding-left
,padding-right
がtheme.spacing(3)
)fontSize
,fontWeight
:fontSize="h6.fontSize"
,fontWeight="fontWeightBold"
(theme.typography.h6.fontSize
,theme.typography.fontWeightBold
)borderRadius
:borderRadius="borderRadius"
(theme.shape.borderRadius
)boxShadow
:boxShadow={3}
(theme.shadows[3]
)- 直接テーマオブジェクトにアクセス:
color={(theme) => theme.palette.error.main}
-
レスポンシブ対応: ブレークポイントごとのスタイルをオブジェクトで指定できます。
javascript
<Box
sx={{
width: { xs: 100, sm: 200, md: 300 }, // 画面幅 xs では 100px, sm 以上で 200px, md 以上で 300px
height: { sm: 100, md: 200 }, // sm 未満ではheightなし、sm 以上で 100px, md 以上で 200px
mt: { xs: 1, md: 3 }, // xs では theme.spacing(1), md 以上で theme.spacing(3)
}}
/>
ブレークポイントの定義はテーマで変更可能です。 -
疑似要素・疑似クラス: CSSセレクタと同様に、
:hover
,:focus
,::before
,::after
などの疑似要素・疑似クラスを指定できます。
javascript
<Button
sx={{
'&:hover': { // ホバー時
bgcolor: 'secondary.dark',
},
'&.Mui-disabled': { // 無効時 (Material UIコンポーネントのクラス名)
opacity: 0.5,
},
'& .MuiButton-label': { // 子要素のクラス名
fontWeight: 'bold',
},
}}
/>
&
は現在のコンポーネント自身を指します。Material UIコンポーネントには、スタイルを上書きするための標準的なクラス名 (MuiButton-root
,MuiButton-label
など) が付与されており、これらを利用して子要素や状態に応じたスタイルを指定できます。 -
メディアクエリ: より複雑なメディアクエリも直接記述できます。
javascript
<Box
sx={{
'@media (min-width: 900px)': { // mdブレークポイントと同等
fontSize: '1.5rem',
},
}}
/>
2. styled()
helper を使ったカスタムコンポーネントの作成
styled()
helperは、既存のReactコンポーネント(DOM要素やMaterial UIコンポーネント)をベースに、独自のスタイルが適用された新しいコンポーネントを作成するのに適しています。これにより、再利用可能なスタイルを持つコンポーネントを定義できます。
“`javascript
import Button from ‘@mui/material/Button’;
import { styled } from ‘@mui/material/styles’;
// primary色で影のないボタン
const NoShadowButton = styled(Button)(({ theme }) => ({
boxShadow: ‘none’,
‘&:hover’: {
boxShadow: ‘none’,
},
// 例えば、ボタンの角を丸くする
borderRadius: theme.shape.borderRadius * 3,
}));
// 使用例
function MyStyledButton() {
return (
影なしカスタムボタン
);
}
“`
styled(Component)(styles)
の形式で使います。Component
にはHTMLタグ名の文字列(例: 'div'
, 'button'
) またはReactコンポーネントを渡します。styles
は、スタイルを定義するCSS-in-JS形式のオブジェクトまたは関数です。関数として渡すと、引数に theme
オブジェクトや props
にアクセスできます。
3. グローバルスタイルの設定とCSSリセット
CssBaseline
コンポーネントは、Material Designに沿った標準的なCSSリセットを適用します。これにより、ブラウザのデフォルトスタイルによる差異を吸収し、一貫した見た目を提供します。アプリケーションのルートで一度だけ使用します。
“`javascript
import { ThemeProvider } from ‘@mui/material/styles’;
import CssBaseline from ‘@mui/material/CssBaseline’;
import myTheme from ‘./myTheme’; // カスタムテーマ
function App() {
return (
{/ アプリケーションコンテンツ /}
);
}
“`
CssBaseline
は、マージンのリセット、デフォルトの背景色とフォントファミリーの設定、Box Sizingの適用などを行います。
4. 特定コンポーネントのデフォルトスタイルの上書き (components
キー)
テーマオブジェクトの components
キーを使うと、アプリケーション全体で特定のMaterial UIコンポーネントのデフォルトpropsやスタイルを一度に設定できます。これは、デザインシステムとして特定のコンポーネントの見た目や挙動を統一したい場合に非常に便利です。
“`javascript
import { createTheme } from ‘@mui/material/styles’;
const myTheme = createTheme({
// … その他のテーマ設定 (palette, typographyなど)
components: {
// Buttonコンポーネントの設定
MuiButton: {
// デフォルトで適用されるprops
defaultProps: {
variant: ‘contained’, // デフォルトのvariantをcontainedに
disableElevation: true, // デフォルトで影を無効に
},
// 特定のバリアントや状態に対するスタイルの上書き
styleOverrides: {
// rootクラス(Buttonの最上位要素)のスタイル
root: ({ theme }) => ({
textTransform: ‘none’, // テキストを大文字にしない
minWidth: 100, // 最小幅を設定
// レスポンシブ対応
[theme.breakpoints.up(‘md’)]: {
minWidth: 150,
},
}),
// outlinedPrimary バリアントのスタイル
outlinedPrimary: {
borderWidth: ‘2px !important’, // !important は避けるべきだが、ライブラリの上書きで必要になる場合がある
},
},
// バリアントごとのpropsやスタイルを定義 (Optional)
variants: [
{
props: { variant: ‘contained’, color: ‘secondary’ },
style: {
backgroundColor: ‘#f50057’, // 例: secondary contained ボタンの色をカスタム
‘&:hover’: {
backgroundColor: ‘#c51162’,
},
},
},
// … その他のカスタムバリアント定義
],
},
// TextFieldコンポーネントの設定
MuiTextField: {
defaultProps: {
variant: ‘outlined’, // デフォルトをoutlinedに
size: ‘small’, // デフォルトをsmallに
},
styleOverrides: {
// rootクラス
root: {
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
},
},
},
// … その他のコンポーネント
},
});
“`
Mui[ComponentName]
の形式でコンポーネントを指定します。defaultProps
は、そのコンポーネントを使用する際に常に適用されるデフォルトのプロパティを設定できます。styleOverrides
は、特定のCSSクラス(例: root
, label
, input
など)に対するスタイルを上書きできます。variants
は、propsの特定の組み合わせ(例: variant="contained"
, color="secondary"
) に対してスタイルを定義できます。
5. テーマのカスタマイズ例
前述のテーマオブジェクトの構造を理解した上で、具体的なカスタマイズ例をいくつか見てみましょう。
-
色の変更: ブランドカラーに合わせて
palette.primary
,palette.secondary
などを変更します。
javascript
const brandTheme = createTheme({
palette: {
primary: {
main: '#FF5722', // 好きな色に変更
},
secondary: {
main: '#4CAF50',
},
// 新しいカスタム色を追加する場合 (モジュールの拡張が必要)
// myCustomColor: {
// main: '#ff00ff',
// },
},
});
カスタム色を追加する場合は、TypeScriptを使用している場合に型の拡張が必要になります。 -
タイポグラフィの変更: 使用するフォントやテキストサイズ、ウェイトなどを変更します。
“`javascript
import ‘@fontsource/noto-sans-jp/400.css’;
import ‘@fontsource/noto-sans-jp/700.css’;const japaneseFontTheme = createTheme({
typography: {
fontFamily: [
‘”Noto Sans JP”‘, // 日本語フォントを優先
‘Roboto’,
‘Arial’,
‘sans-serif’,
].join(‘,’),
h1: {
fontSize: ‘2.5rem’,
fontWeight: 700,
},
body1: {
fontSize: ‘1rem’,
lineHeight: 1.6,
}
},
});
``
@fontsource` などのライブラリで適切に読み込む必要があります。
新しいフォントを導入した場合は、 -
間隔単位の変更:
spacing
の基準値を変更することで、コンポーネント間の余白全体に影響を与えられます。
javascript
const compactTheme = createTheme({
spacing: 4, // デフォルトの8pxから4pxに変更
});
これでtheme.spacing(1)
が4px、theme.spacing(2)
が8px となります。 -
ブレークポイントの変更: レスポンシブデザインの基準となる画面幅を変更します。
javascript
const customBreakpointsTheme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 500, // smを500pxに変更
md: 800, // mdを800pxに変更
lg: 1200,
xl: 1536,
},
},
});
これにより、sx
prop などでのレスポンシブ指定 (sm
,md
など) が新しいブレークポイントで評価されるようになります。
6. ダークモードの実装(Context APIなどと連携)
第2章で触れたダークモードの実装は、アプリケーション全体でモードの状態を管理する必要があります。ReactのContext APIを使うのが一般的な方法です。
“`javascript
// src/contexts/ColorModeContext.tsx (TypeScriptの場合)
import React, { createContext, useState, useMemo, useContext, ReactNode } from ‘react’;
import { ThemeProvider, createTheme, PaletteMode } from ‘@mui/material’;
import CssBaseline from ‘@mui/material/CssBaseline’;
// Contextを作成
const ColorModeContext = createContext({ toggleColorMode: () => {} });
interface ColorModeProviderProps {
children: ReactNode;
}
// Providerコンポーネント
export function ColorModeProvider({ children }: ColorModeProviderProps) {
const [mode, setMode] = useState
const toggleColorMode = React.useCallback(() => {
setMode((prevMode) => (prevMode === ‘light’ ? ‘dark’ : ‘light’));
}, []);
// modeが変更されるたびに新しいテーマをメモ化して生成
const theme = useMemo(
() =>
createTheme({
palette: {
mode,
// ここでライト/ダークモードごとの詳細な色設定も可能
// primary: {
// main: mode === ‘light’ ? ‘#1976d2’ : ‘#90caf9’,
// },
},
// … その他のテーマ設定 (タイポグラフィなど)
}),
[mode],
);
return (
{children}
);
}
// Contextを使用するためのカスタムフック
export const useColorMode = () => useContext(ColorModeContext);
“`
次に、アプリケーションのエントリーポイントで ColorModeProvider
を使用します。
“`javascript
// src/index.tsx (CRAの場合)
import React from ‘react’;
import ReactDOM from ‘react-dom/client’;
import App from ‘./App’;
import { ColorModeProvider } from ‘./contexts/ColorModeContext’; // 作成したProviderをインポート
const root = ReactDOM.createRoot(document.getElementById(‘root’));
root.render(
{/ Providerでアプリケーション全体をラップ /}
);
“`
最後に、テーマを切り替えたいコンポーネントでカスタムフック useColorMode
を使います。
“`javascript
// src/App.tsx (例)
import React from ‘react’;
import Button from ‘@mui/material/Button’;
import Typography from ‘@mui/material/Typography’;
import Box from ‘@mui/material/Box’;
import { useColorMode } from ‘./contexts/ColorModeContext’; // カスタムフックをインポート
function App() {
const { toggleColorMode } = useColorMode(); // Contextから切り替え関数を取得
return (
Material UI ダークモード
{/ ボタンクリックでテーマを切り替え /}
{/ 他のMaterial UIコンポーネントは自動的に現在のテーマが適用されます /}
背景色とテキスト色はテーマによって変わります
);
}
export default App;
“`
これにより、アプリケーション全体でダークモードへの切り替え機能を実装できます。CssBaseline
が背景色やテキスト色などを自動的に調整してくれるため、多くの場合は追加のスタイル変更なしで美しい見た目を実現できます。
5. 発展的なトピック
Material UIをより深く活用するための、いくつか発展的なトピックに触れておきます。
1. Material UIのレンダリングパフォーマンス
Material UI v5はEmotionやStyled ComponentsといったCSS-in-JSライブラリを利用していますが、これらのライブラリはクライアントサイドでスタイルを生成するため、初期レンダリング性能に影響を与える可能性があります。特に大規模なアプリケーションでは、スタイルのインジェクション順序やサーバーサイドレンダリング (SSR) の対応が重要になります。
デフォルトのEmotionでは、特に設定なしでも基本的なパフォーマンスやSSRに対応していますが、より細かい制御やStyled Componentsを使用したい場合は、@mui/material/styles
から提供される StyledEngineProvider
を使用することがあります。ただし、ほとんどのケースではデフォルト設定で十分です。
2. サーバーサイドレンダリング (SSR) 対応
Next.jsのようなSSRフレームワークを使用する場合、Material UIのスタイルをサーバー側で生成し、クライアントに送り返す必要があります。これにより、ユーザーがページを初めて表示したときにスタイルが適用されていない状態(FOUC: Flash Of Unstyled Content)を防ぐことができます。
Next.jsでMaterial UIをSSR対応させるには、通常、pages/_document.js
(または _document.tsx
) をカスタマイズし、EmotionやStyled ComponentsのSSR関連設定を記述する必要があります。公式ドキュメントに詳しい設定方法が記載されていますので、SSRが必要な場合は参照してください。
3. フォームライブラリとの連携
TextField
や他のフォーム関連コンポーネントを複雑なフォームで使用する場合、React Hook FormやFormikのようなフォーム管理ライブラリと連携させることが一般的です。これらのライブラリは、フォームの状態管理、バリデーション、送信処理などを効率化してくれます。
Material UIのフォームコンポーネントは、標準的なHTMLフォーム要素と同様に name
, value
, onChange
, error
, helperText
などのpropsを持っています。これらのpropsをフォームライブラリが提供するAPI(例: React Hook Formの register
や Controller
)と連携させることで、簡単に統合できます。
4. アクセシビリティ (WAI-ARIA)
Material UIは、WAI-ARIAのガイドラインを考慮して設計されています。多くのコンポーネントに適切なロール、状態、プロパティ(role
, aria-
, tabindex
など)がデフォルトで設定されています。
開発者としては、以下の点に注意することで、さらにアクセシブルなUIを作成できます。
* ラベルとヘルパーテキスト: TextField
, Select
, RadioGroup
などで label
や helperText
を適切に使用する。FormControl
, InputLabel
, FormLabel
を組み合わせて使う。
* 代替テキスト: <img>
やアイコンに alt
属性や aria-label
を設定する。
* キーボードナビゲーション: インタラクティブな要素がキーボードで操作できるか確認する。Material UIコンポーネントはデフォルトで対応しているものが多いですが、カスタム要素では注意が必要です。
* フォーカスの管理: モーダルダイアログを開閉した際に、適切にフォーカスを移動させる(Dialog
などはデフォルトで対応)。
* 色のコントラスト: テキストと背景色のコントラスト比が十分か確認する。テーマの色パレットはMaterial Designの基準を満たすように設計されていますが、カスタムカラーや組み合わせによっては注意が必要です。
5. TypeScriptでの利用
Material UIはTypeScriptで記述されており、強力な型定義が提供されています。これにより、開発中にpropsの間違いなどを早期に検知でき、保守性の高いコードを書くことができます。
TypeScriptプロジェクトでMaterial UIを使用する場合、通常は追加の設定は不要です。インストールしたパッケージに含まれる型定義が自動的に認識されます。カスタムテーマに新しいプロパティを追加した場合は、TypeScriptのモジュール拡張機能を使って型の定義を追加する必要があります。
“`typescript
// src/theme.d.ts (例: カスタム色を追加した場合)
import ‘@mui/material/styles’;
declare module ‘@mui/material/styles’ {
interface Palette {
myCustomColor: Palette[‘primary’]; // primaryと同じ構造を持つmyCustomColorを追加
}
interface PaletteOptions {
myCustomColor?: PaletteOptions[‘primary’];
}
}
“`
これにより、テーマオブジェクトや sx
propで theme.palette.myCustomColor
に型安全にアクセスできるようになります。
6. まとめ
この記事では、ReactにおけるUI開発を効率化するための強力なライブラリ、Material UIについて、その導入方法から主要なコンポーネントの使い方、そしてスタイルとテーマのカスタマイズ方法までを詳細に解説しました。
Material UIは、GoogleのMaterial Designに基づいた洗練されたコンポーネント群と、柔軟なスタイル・テーマシステムを提供します。これにより、開発者はデザインの専門知識がなくても、一貫性があり、アクセシビリティにも配慮されたモダンなUIを迅速に構築できます。
記事で紹介したコンポーネントは、Material UIが提供する機能のほんの一部です。しかし、これらの基本的な使い方やスタイリング・テーマの概念を理解すれば、他のコンポーネントも公式ドキュメントを参照しながら容易に使いこなせるようになるはずです。
Material UIの利点と活用方法の再確認:
- デザインの一貫性: Material Designによる統一されたルック&フィール。
- 開発効率: 豊富な既製コンポーネントによる開発時間の短縮。
- カスタマイズ性: テーマシステムとスタイルシステムによる柔軟なデザイン変更。
- アクセシビリティ: デフォルトでのWAI-ARIA対応。
- レスポンシブデザイン: ブレークポイントシステムによる容易なマルチデバイス対応。
これらの利点を活かすことで、より高品質なWebアプリケーション開発が可能になります。
さらなる学習リソース:
Material UIの公式ドキュメント(https://mui.com/)は非常に充実しており、各コンポーネントの詳細なAPIリファレンス、使用例、カスタマイズ方法、高度なトピック(SSR、TypeScript、パフォーマンスなど)に関する情報が網羅されています。この記事で学んだことを基盤に、公式ドキュメントを積極的に参照することをおすすめします。
また、Material UIのGitHubリポジトリや、Stack Overflowなどのコミュニティも、問題解決や情報収集に役立つでしょう。
今後のMaterial UI:
Material UIは継続的に開発が進められており、MUI v5ではスタイルシステムが大きく刷新されました。今後も新しいコンポーネントの追加や機能改善が進められることが予想されます。最新の情報をキャッチアップすることで、常に効率的かつモダンな開発手法を取り入れることができます。
この記事が、あなたがMaterial UIを使ったReact開発を始める上での確かな一歩となることを願っています。 Material UIの豊富な機能と柔軟性を活用して、素晴らしいユーザーインターフェースを構築してください!
総文字数は約5000語になるように調整しました。導入から主要コンポーネント、スタイル・テーマ、発展的なトピックまで網羅し、コード例も豊富に含めました。