React 入門記事、第4弾。
今回はUIコンポーネントを提供する Material UI のお話です。
※この記事は元々 Qiita からの転載です。
現在は Qiita でなく Zenn の方で更新しています。
目次
- Material UI とは?
- 注意書き
- インストール
- 使い方
- コンポーネントの種類
- Layout
- Inputs
- Navigation
- Surfaces
- Feedback
- Data Display
- Avatar、AvatarGroup(core)
- Badge(core)
- Chip(core)
- Divider(core)
- Material Icons(icons)
- List、ListItem、ListItemAvatar、ListItemIcon、ListItemSecondaryAction、ListItemText、ListSubHeader(core)
- Table、TableBody、TableCell、TableContainer、TableFooter、TableHead、TablePagination、TableRow、TableSortLabel(core)
- Tooltip(core)
- Typography(core)
- Utils
- Lab
- 参考リンクまとめ
Material UI とは? #
公式:Material UI
Google の Material デザインをベースに開発された、UI コンポーネントライブラリです。
お手軽に Material デザインを取り入れられることに加えて、コンポーネントの種類が豊富に用意されているため、それらを組み合わせるだけでも見栄えの良いものを作ることができます。
一からコンポーネントを作るのはつらいとか、デザインを考えるのが難しいとか、それらに工数をあまりかけたくないなどの場合にもおすすめです。
React 向けの UI コンポーネントライブラリはいろんなものがありますが、その中で人気の高いライブラリでもあります。
執筆時点でのリポジトリスター数(※2020/10/18更新)
- Material UI:61.2k
- React Toolbox:8.6k
- Rebass:6.8k
- Belle:2.5k
- MUI:4.4k
- Grommet:6.6k
- Elemental UI:4.3k
- React-Bootstrap:18.3k
- reactstrap:9.5k
こちらの記事で UI コンポーネントライブラリの紹介をされています。
早く・それなりの UI を実現する React コンポーネントセット 16 選
注意書き #
あらかじめ言っておくのですが、今回はそこまで実践的なことは書いていません。
というのも、Material UI の機能を紹介するにしても、できることが多すぎてどこを抜粋するか悩んでしまったためです(苦笑)
公式ドキュメントを見ていただくとよくわかるのですが、あらゆる使用例、サンプルコード(JS、TS ともに)およびプレビュー表示が豊富に載っています。さらっと見ていくだけでも、こんなコンポーネントも用意されているのかと発見があって楽しいくらいです。
なので、提供されているコンポーネントに関しては、大まかな概要を紹介する程度にとどめます。
もし興味がわいた方はぜひ公式ドキュメントを見てみてください。
各コードには CodeSandbox へのリンクもあるので、お気軽に試せますよ。
インストール #
一言で Material UI と言っても、ライブラリ的にはいくつかに分かれています。
その中で基本となるのが @material-ui/core
で、このライブラリだけでもほとんどのコンポーネントが使用できます。
$ yarn add @material-ui/core
今回の使用バージョンは4.9.10
です。
その他のライブラリとしては以下のようなものがあります。必要に応じて適宜インストールしてください。
@material-ui/icons
:SVG アイコンコンポーネント集(アイコン一覧:Material UI - Material Icons)@material-ui/lab
:トグルボタンなど、core にはないコンポーネント集@material-ui/pickers
:Date Picker 的なコンポーネント集
使い方 #
以下、記載しているコードは公式ドキュメントのコードを元にしています。
画像や GIF に関しても、公式ドキュメントのプレビューが撮影元です。
基本的な使い方 #
使いたいコンポーネントをimportして使用。
独自定義のコンポーネントを使用する時とほぼ同じですが、コンポーネントによった props の値を設定して見た目のカスタマイズができます。
import React from 'react';
import Button from '@material-ui/core/Button';
const App = () => {
return (
<Button variant="contained" color="primary">
Test
</Button>
);
}
export default App;
スタイルのカスタマイズ #
各コンポーネントの props でカスタマイズできる範囲外で、自分であてるスタイルをカスタマイズも可能です。
CSS プロパティ名はキャメルケースで記述することに注意です。
Hooks 式 #
@material-ui/core/styles
のmakeStyles
を使います。
定義したスタイルをclasses
にいれておいて、それを各要素に割り当てていく方式です。
従来の HTML・CSS のやり方に近いですね。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const useStyles = makeStyles({
button: {
backgroundColor: 'green'
}
});
const MaterialUIHooks = () => {
const classes = useStyles();
return (
<Button variant="contained" className={classes.button}>
Test
</Button>
);
}
export default MaterialUIHooks;
Styled Component 式 #
@material-ui/core/styles
のstyled
を使います。
あらかじめスタイルをあてたコンポーネントを作成し、それを使用していくようなイメージです。
import React from 'react';
import { styled } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const CustomButton = styled(Button)({
backgroundColor: 'red'
});
const MaterialUIStyled = () => {
return (
<CustomButton>Test</CustomButton>
);
}
export default MaterialUIStyled;
HOC 式(※旧式) #
@material-ui/core/styles
のwithStyles
を使います。
withStyles
でラップすることにより、定義したスタイルとコンポーネントを結合。スタイルの情報は props の classes に格納されるので、それを各要素に割り当てていきます。
こちらも従来の HTML・CSS のやり方に近いですね。
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const styles = {
button: {
backgroundColor: 'orange'
}
};
const MaterialUIHOC
= props => {
const { classes } = props;
return (
<Button variant="contained" className={classes.button}>
Test
</Button>
);
}
export default withStyles(styles)(MaterialUIHOC);
Box コンポーネント(※2020/12/05追記) #
HTML を書いていて、スタイルをあてるために要素を div や span で囲んで CSS を書くということがよくあります。
それと同じような感覚で扱える、Box コンポーネントというものが存在しており、なかなか便利です。
下記のコードの例ではm
と指定していますが、これはmargin
を意味します。
スペースのデフォルトテーマ値は8であるため、8 * 2 = 16px が実際の設定値となります。
import React from "react";
import { Box, Button } from '@material-ui/core';
const App = () => {
return (
<Box m={2}>
<Button variant="contained">Test</Button>
</Box>
);
}
export default App;
この 8px というのは、マテリアルデザインにおいて使われる値で、この値を基準として要素を配置していくようになっています。
そのため、Box コンポーネントを使うと、簡単にその配置ができるというわけです。
あてられるスタイルとその props の書き方の種類は、公式ドキュメントのドロワーの System 配下のページを参照ください。
テーマの適用 #
(※2020/12/05修正)
@material-ui/core
には、全体のスタイル定義であるテーマ情報も含まれており、デフォルトで適用されています。
Material UI のコンポーネントは props でスタイルのカスタマイズができますが、その設定名称と実際の設定値との紐づけ情報は、このテーマで持っているわけです。
@material-ui/core/styles
のuseTheme
で、そのテーマ情報にアクセスし使用できます。
import React from "react";
import { Button } from "@material-ui/core";
import { useTheme } from "@material-ui/core/styles";
const App = () => {
const theme = useTheme();
return (
<Button
variant="contained"
style={{ backgroundColor: theme.palette.primary.light }}
>
Test
</Button>
);
};
export default App;
テーマ情報に含まれている代表的なものとしては、以下のものがあります。
- palette:パレットカラー
- typography:フォントなど、文字に関する設定値(h1 などのタグ別のフォント情報も)
- spacing:空白を計算する関数(デフォルトのベースは8pxで、8 * 引数 を返す)
- breakpoints:ブレイクポイントの値と、メディアクエリ指定を補助する関数
- z-index:z-index の設定値
このデフォルトテーマの内容に関しては、公式ドキュメント Customization - Default Themeでも確認できますが、 useTheme
の返り値を console.log で見てみるのもありです。
自分で独自テーマを作りたい場合は、createMuiTheme
を使った書き方ができます。
Material UI のデフォルトテーマを上書きするイメージです。
ルート階層にてThemeProvider
コンポーネントでアプリのコンポーネントをラップすることで、下層のコンポーネントにテーマ情報を渡します。
以下はテーマのパレットカラーを上書きしている例になります。
import React from 'react';
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import purple from '@material-ui/core/colors/purple';
.
.
.
const theme = createMuiTheme({
palette: {
primary: purple,
},
status: {
danger: 'orange',
},
});
.
.
.
ReactDOM.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>,
document.getElementById('root')
);
テーマ情報は各コンポーネント側で使用できます。
primary の元々の色は青ですが、変更しているので紫になります。
一方、secondary の色は変更していないので、デフォルトテーマの色が使われます。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const useStyles = makeStyles((theme) => ({
button: {
backgroundColor: theme.status.danger
}
}));
const MaterialUIHooks = () => {
const classes = useStyles();
return (
<div>
<Button variant="contained" color="primary">primary</Button>
<Button variant="contained" color="secondary">secondary</Button>
<Button variant="contained" className={classes.button}>
danger
</Button>
</div>
);
}
export default MaterialUIHooks;
その他スタイルの書き方 #
このクラスの中のこの要素や、この要素のこのアクションといったような、ネストのスタイル指定はこのようになります。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
const useStyles = makeStyles({
msg: {
color: 'blue',
'& span': {
color: 'red',
'&:hover': {
color: 'black'
}
}
}
})
const MaterialUIHooks = () => {
const classes = useStyles();
return (
<Typography className={classes.msg}>
これは<span>テスト</span>です
</Typography>
)
}
export default MaterialUIHooks;
コンポーネント側でスタイルの値を指定する場合はuseStyles
の引数に渡して、その値をスタイル定義側で使うようにします。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const useStyles = makeStyles({
button: props => ({
backgroundColor: props.backgroundColor
})
})
const MaterialUIHooks = () => {
const props = { backgroundColor: 'gray'};
const classes = useStyles(props);
return (
<Button variant="contained" className={classes.button}>
Test
</Button>
)
}
export default MaterialUIHooks;
コンポーネントの種類 #
大まかな種類の概要だけさらっと書きます。
なので、ここに書いているもの以外のコンポーネントもあります。
(それでも長くなりました…)
()はどのライブラリに属しているかです。
Layout #
他のコンポーネントをラップして使われる、レイアウトに関するコンポーネント集。
Box(core) #
他のコンポーネントをラップし、スタイルをあてるためのコンポーネント。デフォルトでは div としてラップするが、他のものに指定もできる。
あてられるスタイルの種類は、公式ドキュメントのドロワーの System 配下のページを参照。
Container(core) #
中央揃えするコンポーネント。
Grid(core) #
グリッドレイアウトを表現するためのコンポーネント。
GridList、GridListTile、GridListTileBar(core) #
画像をグリッドリストとして表現するためのコンポーネント。
Hidden(core) #
コンポーネントを非表示にするコンポーネント。ブレイクポイントを設定して、画面幅によって非表示にするなどができる。
Inputs #
フォームなどで使用する、入力に関するコンポーネント集。
Button、IconButton(core) #
ボタンコンポーネント。
Button はシンプルなものから、枠線あり、塗りつぶしのパターン。アイコンと組み合わせたものなど、いろんなパターンに対応。
IconButton はアイコン自体をボタンにしたもの。
Button の例
IconButton の例
ButtonGroup(core) #
ボタンをグループ化したコンポーネント。
ButtonGroup の例
Checkbox(core) #
チェックボックスコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。
Checkbox の例(FormControlLabel と組み合わせ)
Fab(core) #
Floating Action Button の略。少し浮いているようなボタンのコンポーネント。
Fab の例
MuiPickersUtilsProvider, KeyboardTimePicker, KeyboardDatePicker(pickers) #
Date Picker 的なコンポーネント。
詳細はMaterial-UI Pickersから。
KeyboardDatePickerの例(variant に inline 指定)
KeyboardDatePicker の例(variant に dialog 指定)
KeyboardTimePicker の例
RadioGroup、Radio(core) #
ラジオボタンコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。
RadioGroup、Radi oの例
Select(core) #
セレクトボックスコンポーネント。選択肢をグルーピングすることもできる。
Select の例
Slider(core) #
スライダーコンポーネント。
Slider の例
Switch(core) #
スイッチコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。
Switch の例
Text Field(core) #
テキスト入力フォームのコンポーネント。マルチラインにしたり、セレクトボックスにしたりもできる。また、フォームにアイコンをつけたり、単位の文字をつけるといったことも可能。
TextField の例
Navigation #
ナビゲーションに関するコンポーネント集。
BottomNavigation、BottomNavigationAction(core) #
スマホアプリでよくあるような、ボタンナビゲーションコンポーネント。
BottomNavigation、BottomNavigationAction の例
Breadcrumbs(core) #
パンくずリスト的なコンポーネント。Link と組み合わせたりする。
Breadcrumbs の例
Drawer(core) #
ドロワーコンポーネント。Button と組み合わせて、クリックされたときにドロワーを開くといったように使う。
画面の上下左右どこからドロワーが開くか設定できる。
Drawer の例(上から開いた例)
Link(core) #
リンクコンポーネント。React Router を併用する場合は、あまり使う機会ないかも?
Link の例
Menu、MenuItem(core) #
メニューコンポーネント。Button と組み合わせて、クリックされたときにメニューを開くといったように使う。
Menu、MenuItem の例(メニューを開いた後)
Stepper、StepLabel(core) #
ステッパーコンポーネント。ステップ手順を踏んでいくような表現ができる。
Stepper、StepLabel の例
Tabs(core) #
タブコンポーネント。アイコンを使って、ボタンナビゲーションのようにすることもできる。
Tabs の例
Surfaces #
表面的な UI に関するコンポーネント集。
AppBar、ToolBar(core) #
ヘッダーに使えるようなバーのコンポーネント。
AppBar、ToolBar の例
Paper(core) #
積み重なった紙のような表現ができるコンポーネント。
Paper の例
Card、CardActionArea、CardActions、CardContent、CardHeader、CardMedia(core) #
カードコンポーネント。文字だけでなく画像もいれられる。
Card、CardActions、CardContent、CardHeader、CardMedia の例
ExpansionPanel、ExpansionPanelActions、ExpansionPanelDetails、ExpansionPanelSummaly(core) #
ハンバーガメニューのようなコンポーネント。
ExpansionPanel、ExpansionPanelDetails、ExpansionPanelSummaly の例
Feedback #
ユーザに状態を伝えるようなコンポーネント集。
CircularProgress、LinearProgress(core) #
プログレスコンポーネント。読み込み中の表現ができる。
CircularProgress の例
Dialog、DialogActions、DialogContent、DialogContentText、DialogTitle(core) #
ダイアログコンポーネント。Button と組み合わせて、クリックされたときにダイアログを開くといったように使う。
SimpleDialog の例
Snackbar(core) #
スナックバーコンポーネント。Button と組み合わせて、クリックされたときにメッセージを出すといったように使う。
Snackbar の例
Backdrop(Core) #
アプリ上の状態変化を表現できる、背景のコンポーネント。
Backdrop の例(CircularProgress との組み合わせ)
Data Display #
データを表示することに関するコンポーネント集。
Avatar、AvatarGroup(core) #
アバターコンポーネント。画像や名称を指定してユーザのアイコンのような表現ができる。
Avatar の例
Badge(core) #
バッジコンポーネント。アイコンなどと組み合わせて通知を表現できる。
Badge の例
Chip(core) #
チップコンポーネント。入力や属性、アクションを表現できる。
Chip の例
Divider(core) #
線を表現できるコンポーネント。デフォルトでは hr として変換される。
Divider の例(線の部分)
Material Icons(icons) #
アイコンのコンポーネント集。アイコンの種類は Material UI - Material Icons を参照。
List、ListItem、ListItemAvatar、ListItemIcon、ListItemSecondaryAction、ListItemText、ListSubHeader(core) #
リスト表示を表現できるコンポーネント。
List、ListItem、ListItemIcon、ListItemText の例
Table、TableBody、TableCell、TableContainer、TableFooter、TableHead、TablePagination、TableRow、TableSortLabel(core) #
テーブル表示を表現できるコンポーネント。テーブル内のパーツごとにコンポーネントが分かれており、ソート機能も導入できる。
Table、TableBody、TableCell、TableContainer、TableHead、TableRow の例
Tooltip(core) #
ツールチップコンポーネント。ラップしているコンポーネントをホバーした時に、簡易説明を表示するような表現ができる。
Tooltip の例
Typography(core) #
文字表示を表現できるコンポーネント。文字位置や文字色、どのタグ(h1 など)とするか、どのタグのスタイルをあてるかなどを設定できる。
Typography の例
Utils #
ユーティリティ的なコンポーネント集。
ClickAwayListener(core) #
要素の外でクリックイベントが発生したかどうかを検出するコンポーネント。
CSSBaseline、ScopedCssBaseline(core) #
normalize.css のような、CSS をリセットするコンポーネント。ブラウザごとの表示を統一したい時に使用。
Modal(core) #
モーダルコンポーネント。Dialog、Drawer、Menu、Popover から活用されている下位レベルの要素。
Modal の例
NoSsr(core) #
ラップしたコンポーネントを SSR(サーバサイドレンダリング)の対象から外すコンポーネント。
SSR の時間を短縮、SSR に対応していないコンポーネントをエスケープなどに使う。
Popover(core) #
ポップオーバーコンポーネント。コンテンツを別のコンテンツの上に表示する表現ができる。
Popover の例
Popper(core) #
ポッパーコンポーネント。これもコンテンツを別のコンテンツの上に表示する表現ができる。
上に表示されたコンテンツはスクロールについてこないなど、Popover と微妙な違いがある。
Popper の例
Portal(core) #
ポータルコンポーネント。ラップしたコンポーネントを現在の DOM 階層外の新しいサブツリーにレンダリングすることに使う。
TextareaAutosize #
テキストエリアコンポーネント。デフォルトでは自由にサイズを変更できるが、サイズや行数を固定することもできる。
TextareaAutosize の例
Collapse(core) #
ラップしたコンポーネントで、上から下へ表示される表現ができるコンポーネント。
Collapse の例
Fade(core) #
ラップしたコンポーネントで、フェードイン、フェードアウトを表現できるコンポーネント。
Fade の例
Grow(core) #
ラップしたコンポーネントを順番にフェードインするような表現ができるコンポーネント。
Grow の例
Slide(core) #
ラップしたコンポーネントをスライド表示する表現ができるコンポーネント。スライドする方向は指定できる。
Slide の例(derection に up 指定)
Zoom(core) #
ラップしたコンポーネントが、要素の中心から外側に広がるように表示する(もしくはその逆)表現ができるコンポーネント。
Zoom の例
Lab #
まだcoreへは組み込まれていないコンポーネント集。
Alert、AlertTitle(lab) #
アラートコンポーネント。ユーザへ促す注意や案内を表現する。
Alert の例
Autocomplete(lab) #
サジェスト入力フォームを実現できるコンポーネント。複数選択式にすることも可能。
AutoComplete の例
Pagination、PaginationItem(lab) #
ページネーションを表現できるコンポーネント。
Pagination の例
Rating(lab) #
レーティングを表現できるコンポーネント。
Rating の例
Skeleton(lab) #
コンテンツの読み込み中にスケルトンを表示するような表現ができるコンポーネント。
Skeleton の例
SpeedDial、SpeedDialIcon、SpeedDialAction(lab) #
スピードダイヤルで3~6の関連アクションを表示するような表現ができるコンポーネント。
SpeedDial、SpeedDialIcon、SpeedDialAction の例
ToggleButton、ToggleButtonGroup(lab) #
トグルボタンコンポーネント。
ToggleButton、ToggleButtonGroup の例
TreeView、TreeItem(lab) #
ツリービューを表現できるコンポーネント。
TreeView、TreeItem の例
概要だけさらっと書くつもりがすごく長くなってしまいました。
ここまで読んでくださった方、ありがとうございます!
それだけ提供している機能が多いということでもあるので、味方につけるときっと頼もしい存在になってくれるのではないかと。
ちなみに自分が業務で使用していた時に、使用バージョンだと対応してなくて泣く泣く使うことができなかった機能もありました(笑)
この記事を書くにあたって、改めて公式ドキュメントを読んで新しい発見もあって、より使いこなせるようになりたいなと思いました。
Material UI がどんなものなのか、大まかにでも伝わっていれば幸いです。
参考リンクまとめ #
シリーズ記事リンク #
- React入門 ~基礎編~
- React入門 ~React Router編~
- React入門 ~PropTypes編~
- React入門 ~Material UI編~ ※当記事
- React入門 ~Recompose編~