Closed6

MUI(Material UI v5) メモ

よしよし

新ブランド

Material UI → MUI へ名称変更。

Material-UIをGoogleと混同している人や、Material Designの同義語として多くの人が見ているため、MaterialDesignとの強い関連性を断ち切っています。

多くの人がすでにMaterial-UIの省略形として使用しています。さらに重要なことは、コンポーネントのスタイルなし/ヘッドレスバージョン、MDの代替としてのまったく新しいセカンドデザインシステム、より野心的なイニシアチブなど、マテリアルデザインに直接結合されていない製品のリリースを可能にすることです。

ロゴも微妙に新しくなった。

リポジトリ名はそのまま
https://github.com/mui-org/material-ui

公式サイト

それに伴い、ドメインも変化。
https://material-ui.com/


https://mui.com/
https://v4.mui.com/

公式サイトのデザインも一新された。

パッケージ構成

名称変更

@material-ui/core -> @mui/material
@material-ui/system -> @mui/system
@material-ui/unstyled -> @mui/core
@material-ui/styles -> @mui/styles
@material-ui/icons -> @mui/icons-material
@material-ui/lab -> @mui/lab
@material-ui/types -> @mui/types
@material-ui/styled-engine -> @mui/styled-engine
@material-ui/styled-engine-sc ->@mui/styled-engine-sc
@material-ui/private-theming -> @mui/private-theming
@material-ui/codemod -> @mui/codemod
@material-ui/docs -> @mui/docs
@material-ui/envinfo -> @mui/envinfo

インストール方法

  • React:16.8.0 以上
  • react-dom:16.8.0 以上
npm install @material-ui/core
or
yarn add @material-ui/core

  • React:17.0.0 以上
  • react-dom:17.0.0 以上
// emotion を使う場合
npm install @mui/material @emotion/react @emotion/styled
or
yarn add @mui/material @emotion/react @emotion/styled

// styled-components を使う場合
npm install @mui/material @mui/styled-engine-sc styled-components
or
yarn add @mui/material @mui/styled-engine-sc styled-components

パッケージ名自体が変わっているため、4系と5系の共存も出来るっぽい。
パフォーマンスの比較とか、部分的に移行していくとかできそう。

よしよし

新たなスタイルシステムによる、スタイルのカスタマイズ性向上

v4 では、スタイルシステムの実体として JSS が使われていた。
https://github.com/cssinjs/jss

しかし、以下のような問題を抱えていた。

  1. styled-components や emotion 、linaria などのスタイルライブラリと互換性があったが、多くの開発者はmakeStylesAPI を学ぶ必要性を感じていた
  2. JSS の静的 CSS 生成は十分高速であり、emotion よりも高速であったが、動的スタイル生成は遅い問題があった。これでは、目指すカスタマイズDXの目標を達成できなかったため、再実装する必要があった
  3. 多くの開発者から styled-components に移行するよう提唱されていた。これにより、現在維持しているカスタム ReactJSS ラッパーを削除できるようになる + カスタムスタイリングソリューションの維持にかなり時間のかかる問題の解消ができる

これを解決するために、共通インタフェースを定義したうえで、その実装を作成

  • @mui/styled-engine:emotion で実装(デフォルト)
  • @mui/styled-engine-sc:styled-components で実装

これにより、開発者は異なるスタイルのエンジン間で交換できます。たとえば、スタイル付きコンポーネントのユーザーは、感情とスタイル付きコンポーネントをバンドルする必要がなくなり、それぞれのサーバー側レンダリングを構成する必要もなくなりました。スワップはどのように機能しますか?ReactからPreactまでと同じ方法です。

v5 では、emotion(デフォルト)と styled-components を採用。
https://github.com/emotion-js/emotion
https://github.com/styled-components/styled-components

emotion に移行したのは、パフォーマンス向上のため
Box コンポーネントのパフォーマンスの比較
https://codesandbox.io/s/zlh5w?file=/src/App.js

なお、@mui/stylesで以前の JSS を使い続けることも出来る。
(基本的には移行を推奨)

よしよし

コンポーネント

基本的な使い方

シンプルな例だと、インポート元が変わるくらい。

v4

import { VFC } from 'react';
import Button from '@material-ui/core/Button';

const App: VFC = () => {
  return (
    <Button variant="contained" color="primary">
      Test
    </Button>
  );
}

export default App;

v5

import { VFC } from 'react';
import Button from '@mui/material/Button';

const App: VFC = () => {
  return (
    <Button variant="contained" color="primary">
      Test
    </Button>
  );
}

export default App;

新しいコンポーネント

Grid

機能改善
行と列の間隔をサポート

<Grid container rowSpacing={1} columnSpacing={2} />

すべての props でレスポンシブ値をサポート

<Grid container spacing={{ xs: 2, md: 3 }} />

12とは異なる列数のサポート

<Grid container columns={16}>

CSS グリッドを使用する代替実装

<Box display="grid" gridTemplateColumns="repeat(12, 1fr)" gap={2}>
  <Box gridColumn="span 8">
    <Item>xs=8</Item>
  </Box>
  <Box gridColumn="span 4">
    <Item>xs=4</Item>
  </Box>
  <Box gridColumn="span 4">
    <Item>xs=4</Item>
  </Box>
  <Box gridColumn="span 8">
    <Item>xs=8</Item>
  </Box>
</Box>

Material Icon

5つの異なるテーマで600の新しいアイコンをリリース。
パッケージとしては@mui/icons-material

https://mui.com/components/material-icons/

v4

  • Filled:1117
  • Oulined:1116
  • Rounded:1109
  • Two tone:1107
  • Sharp:1106

v5

  • Filled:1780
  • Oulined:1780
  • Rounded:1775
  • Two tone:1771
  • Sharp:1769

Stack

https://mui.com/components/stack/
1次元レイアウトを処理するためのコンポーネント。
Figma の auto layout に似ている。

パッケージ移行したコンポーネント

pickers

@material-ui/pickersが lab に取り込まれた。
日付範囲ピッカーはProプランの一部になるが、他の日付ピッカーコンポーネントはMITライセンス。

そのほか

lab にあったものが、core に取り込まれた。

Inputs
https://mui.com/components/autocomplete/
https://mui.com/components/rating/
https://mui.com/components/toggle-button/

Feedback
https://mui.com/components/skeleton/

Navigation
https://mui.com/components/speed-dial/
https://mui.com/components/pagination/

lab に追加されたコンポーネント

Inputs
https://mui.com/components/buttons/#loading-buttons
ボタンの二度押し防止、読み込み中、保留などを表現できる。

Lab
https://mui.com/components/trap-focus/

このコンポーネントは、DOMノード内でキーボードフォーカスをトラップします。たとえば、アクセシビリティの理由でコンポーネントからタブアウトするのを防ぐためにモーダルによって使用されます。

https://mui.com/components/masonry/

組積造は、構成可能なギャップを備えた同じ幅と可変高さのブロックとして、さまざまなサイズのコンテンツをレイアウトします。
このコンポーネントの優れた使用例の1つは、Gridコンポーネントを使用するとスペースが無駄になる場合です。ダッシュボードで頻繁に使用されます。

よしよし

スタイルソリューション

「新たなスタイルシステムによる、スタイルのカスタマイズ性向上」でも記述したが、スタイルシステムが JSS から emotion(もしくは styled-components)に移行された。
それに伴い、コンポーネントのスタイルカスタマイズのやり方も新しくなった。

v4 では主に以下のやり方があった

  • makeStyles 式
  • styled-components 式
  • withStyles 式
  • インラインスタイル式

v4(makeStyles の例)

import { VFC, ReactNode } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles({
  button: {
    backgroundColor: 'green'
  }
});

type Props = {
  children: ReactNode;
}

const HooksButton: VFC<Props> = ({ children }) => {
  const classes = useStyles();

  return (
    <Button variant="contained" className={classes.button}>
      {children}
    </Button>
  );
}

export default HooksButton;

v4(styled-components)

import { VFC, ReactNode } from 'react';
import { styled } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const CustomButton = styled(Button)({
  backgroundColor: 'red'
});

type Props = {
  children: ReactNode;
}

const StyledButton: VFC<Props> = ({ children }) => {
  return <CustomButton variant="contained">{children}</CustomButton>;
};

export default StyledButton;

v5 では以下が主なやり方になる

  • styled-components 式
  • sx props 式
    インラインスタイル方式も一応使えはする。

v5(styled-components + オブジェクト形式)

import { VFC, ReactNode } from 'react';
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';

const CustomButton = styled(Button)({
  backgroundColor: 'red'
});

type Props = {
  children: ReactNode;
}

const StyledButton: VFC<Props> = ({ children }) => {
  return <CustomButton variant="contained">{children}</CustomButton>;
};

export default StyledButton;

v5(styled-components + テーマ受け取り + オブジェクト形式)

import { VFC, ReactNode } from 'react';
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';

const CustomButton = styled(Button)(({ theme }) => ({
  backgroundColor: theme.palette.info.light
}));

type Props = {
  children: ReactNode;
}

const StyledButton: VFC<Props> = ({ children }) => {
  return <CustomButton variant="contained">{children}</CustomButton>;
};

export default StyledButton;

sx props

https://mui.com/system/the-sx-prop/

  1. コンテキストを切り替えると時間が無駄になります。スタイル付きAPIを使用すると、スタイル付きコンポーネントの使用とそれらが定義されている場所の間を常にジャンプする必要があります。スタイルの説明を必要な場所に移動できますか?
  2. 名前を付けるのは難しいです。スタイル付きコンポーネントの適切な名前を見つけるのに苦労したことがありますか?さらに別のコンポーネントを作成して名前を付ける必要をなくすことができますか?
  3. UIで一貫性を強制することは困難です。これは、複数の人がアプリケーションを構築している場合に特に当てはまります。デザイントークンの選択とその使用方法、テーマ構造のどの部分をどのCSSで使用するかについて、チームのメンバー間で調整を行う必要があるためです。プロパティなど。

これらの問題を解決するために作られたもの。
styled を使うまでもない、一回きりのスタイルを定義するのに使える props。
一見、インラインスタイルと同じように見えるが、特定の CSS プロパティのキーと値が、テーマとマッピングされたものになっている。

import Box from '@mui/material/Box';

const BoxSx = () => {
  return (
    <Box
        sx={{
          boxShadow: 1, // theme.shadows[1]
          color: 'primary.main', // theme.palette.primary.main
          m: 1, // margin: theme.spacing(1)
          p: {
            xs: 1, // [theme.breakpoints.up('xs')]: { padding: theme.spacing(1) }
          },
          zIndex: 'tooltip', // theme.zIndex.tooltip
        }}
      >
        test
    </Box>
  );
}

export default BoxSx;

コールバックで、テーマ情報を受け取って使うということも出来る

<Box sx={{ height: (theme) => theme.spacing(10) }} />

API トレードオフ

以下の4つの CSSコンポーネントユーティリティとなるコンポーネントのみ、システムプロパティを props として受け入れる。

  • Box
  • Stack
  • Typography
  • Grid

といっても、すべてのコンポーネントで sx props が使えるようだったので、
~これの意味がよくわからなかったが、Button コンポーネントで color props と sx で bgColor を設定したところ、color props の方が優先された。~
普通に共存できた。CSS プロパティが重複した場合は sx props のスタイルの方が優先された。


sx props を使わずとも、直接システムプロパティが使えるのが

  • Box
  • Stack
  • Typography
  • Grid

これ以外のコンポーネントは sx props を使えば、システムプロパティを使えるようになる

という意味っぽい。
CSSコンポーネントユーティリティ において、
直接システムプロパティを使うのと、sx props を使うのとで CSS プロパティが被った時は後者のみ適用される。

このスクラップは2021/09/26にクローズされました