MUI (Material UI) ライブラリのReactでの使い方

MUIライブラリとは

MUIとはReact用のUIコンポーネントライブラリです。

以前はMaterial UIという名称でしたが、Googleが提唱する「Material Design」のUIを「Material UI」と言うことがあるので、混同を避けるためにMUIに変更されました。

MUIには以下の6つの特徴があります。

1. Material Designに基づくスタイル

GoogleのMaterial Designガイドラインに準拠しており、洗練されたモダンなUIを使用できます。

ボタンや入力フォームなど、一貫性のあるコンポーネントを使って簡単にデザインを統一できます。

2. Reactとの相性が良い

React開発者向けに最適化されており、簡単にUIコンポーネントを実装できます。

3. カスタマイズの柔軟性

色やスタイルなどをプロジェクトに合わせて簡単にカスタマイズできます。

4. レスポンシブデザイン対応

モバイルファーストの設計なので、レスポンシブデザインに対応しています。

5. アクセシビリティ

ARIA属性などのアクセシビリティに配慮した設計がされています。

6. TypeScriptのサポート

TypeScriptをフルサポートしているため、型安全なコードを簡単に書けます。

MUIライブラリの使用方法

まず、MUIの説明に必要なのでReactの開発環境を以下のコマンドで作成してください。

npm create vite@latest my-react-mui -- --template react-swc-ts

次に作成した開発環境にMUIをインストールします。

MUIではRobotoフォントとアイコンも使用するため、以下のコマンドでRobotoフォントとアイコンもインストールします。

npm i -D @mui/material @emotion/react @emotion/styled @mui/icons-material @fontsource/roboto

フォントをインストールしたらmain.tsxに以下のコードを貼り付けて、Robotoフォントが読み込まれるようにします。

main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

この時点ではRobotoフォントが適用されるのはMUIのコンポーネントだけです。

例えばh1タグなどのMUI以外の箇所でも適用させたい場合は、index.cssの:rootなどでfont-familyにRobotoを指定する必要があります。

index.css
:root {
  font-family: Roboto, Helvetica, Arial, sans-serif;
}

Buttonコンポーネントを使用する

MUIコンポーネントを使用するにはMaterial UI componentsの中から使用するコンポーネントを選択して、インポートして使用します。

この記事ではButtonコンポーネントを使用した例をメインに説明します。

Stackコンポーネントも使用していますが、これはGridコンポーネントのようなもので、Stackは一次元のレイアウトに最適で、Gridは縦と横の両方の配置が必要な場合に適しています。

Buttonコンポーネントを使用するには「import Button from '@mui/material/Button';」でButtonをインポートして以下のようにButtonコンポーネントとvariant属性を追加して使用します。

Buttonコンポーネントはaタグのようにhrefやtarget属性も使用できます。

App.tsx
import Stack from '@mui/material/Stack'
import Button from '@mui/material/Button'

function App() {
  return (
    <>
      <Stack spacing={2} direction="row">
        <Button variant="text">Text</Button>
        <Button variant="contained">Contained</Button>
        <Button variant="outlined">Outlined</Button>
      </Stack>
      
      <hr />

      <Stack spacing={2} direction="row">
        <Button variant="contained">Contained</Button>
        <Button variant="contained" disabled>
          Disabled
        </Button>
        <Button variant="contained" href="https://iwb.jp/" target="_blank">
          Link
        </Button>
      </Stack>
    </>
  )
}

export default App
MUI Button

MUI Button sample

Buttonには3つのvariant (バリエーション)があります。

text(デフォルト)、contained、outlinedの3つのvariantがあり、containedがよく使われます。

containedボタンには影が付いていますが、disableElevation属性を付ければ影を消せます。

TSX
<Button variant="contained" disableElevation>
  Contained No Shadow
</Button>
MUI Button disableElevation

MUIのデフォルトの属性やCSSの変更方法

MUIのButtonコンポーネントは <Button variant="contained" disableElevation>のものが使用されることが多いですが、毎回これらの属性を書くのは手間がかかります。

そんなときはcreateThemeでコンポーネントのデフォルト設定を変えて、ThemeProviderを使って適用すれば属性の追加を省略できます。

また、createThemeを使用すればスタイルシートを上書きできるので、例えばボタンの最小幅を150pxに変更したい場合はstyleOverridesで変更できます。

App.tsx
import { createTheme, ThemeProvider } from '@mui/material/styles'
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';

const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        variant: 'contained',
        disableElevation: true,
      },
      styleOverrides: {
        root: {
          minWidth: '150px',
        },
      },
    },
  },
})

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Stack spacing={2} direction="row">
        <Button>Button 1</Button>
        <Button>Button 2</Button>
        <Button>Button 3</Button>
      </Stack>
    </ThemeProvider>
  )
}

export default App

MUI createTheme sample

クリックイベントを追加する

クリックイベントを追加するにはonClickを追加します。

App.tsx
<Button onClick={() => alert('click!')}>click!</Button>

color属性でボタンの色を変更する

Buttonの色はcolor属性で6つの値が用意されています。

App.tsx
<Button color="primary">primary</Button>
<Button color="secondary">secondary</Button>
<Button color="info">info</Button>
<Button color="warning">warning</Button>
<Button color="success">success</Button>
<Button color="error">error</Button>

colorの色を追加したい場合はcreateThemeのpaletteで追加できます。

App.tsx
import { createTheme, ThemeProvider } from '@mui/material/styles'
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';

declare module '@mui/material/styles' {
  interface Palette {
    gold: Palette['primary'];
  }

  interface PaletteOptions {
    gold?: PaletteOptions['primary'];
  }
}

declare module '@mui/material/Button' {
  interface ButtonPropsColorOverrides {
    gold: true;
  }
}

const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        variant: 'contained',
        disableElevation: true,
      },
    },
  },
  palette: {
    gold: {
      main: '#E3D026',
      light: '#E9DB5D',
      dark: '#A29415',
      contrastText: '#242105',
    },
  },
})

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Stack spacing={2} direction="row">
        <Button color="gold">gold</Button>
      </Stack>
    </ThemeProvider>
  )
}

export default App

size属性でボタンのサイズを変更する

Stackを使用しているとsizeを指定してもサイズを変更できないので、以下の例ではBoxに変えています。

App.tsx
import { createTheme, ThemeProvider } from '@mui/material/styles'
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';

const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        variant: 'contained',
        disableElevation: true,
      },
    },
  },
})

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Box sx={{ '& button': { m: 1 } }}>
        <Button size="small">Small</Button>
        <Button size="medium">Medium</Button>
        <Button size="large">Large</Button>
      </Box>
    </ThemeProvider>
  )
}

export default App

startIconでButtonにアイコンを追加する

@mui/icons-materialをインポートして、startIconでアイコンのコンポーネントを指定すればボタンにアイコンを表示できます。

App.tsx
import { createTheme, ThemeProvider } from '@mui/material/styles'
import Button from '@mui/material/Button';
import DeleteIcon from '@mui/icons-material/Delete';
import SendIcon from '@mui/icons-material/Send';
import Stack from '@mui/material/Stack';

const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        variant: 'contained',
        disableElevation: true,
      },
    },
  },
})

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Stack direction="row" spacing={2}>
        <Button startIcon={<DeleteIcon />}>
          Delete
        </Button>
        <Button endIcon={<SendIcon />}>
          Send
        </Button>
      </Stack>
    </ThemeProvider>
  )
}

export default App

まとめ

MUIとはReact用のUIコンポーネントライブラリで、インポートすることで簡単に利用できる。

この記事ではButtonコンポーネントを中心に説明しましたが、公式サイトのMaterial UI components
のページには多彩なコンポーネントが用意されています。


MUIを使えば、レスポンシブでモダンなWebアプリケーションを効率的に開発でき、Reactコンポーネントを使って再利用可能なUIを作成できるので、積極的に使用することをオススメします。

Material UI components