SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現場で役立つ! React向けライブラリ詳説

綺麗なコンポーネントを容易に導入できるMaterial-UIを紹介【前編】

現場で役立つ! React向けライブラリ詳説 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

テーマを設定する

 続いて、テーマの設定方法を解説します。前述の通り、Material Designはテーマカラーを設定することでオリジナリティのあるデザインを生み出すことができます。試しに、CodeZineのカラーリングを参考にして、テーマを作ってみましょう。

 Material Designの色システムでは、19種類のベースカラーが用意されており、それの濃淡を数値で表現します。探してみると、CodeZineのメインカラーと近いのはLightBlueの800番、アクセントカラーと近いのはTealの200番でした(図7)。

図7:CodeZineの色合いに近いものを選んだ
図7:CodeZineの色合いに近いものを選んだ

 それでは、これをテーマの形に落とし込んでみましょう。リスト3はテーマを適用する実装です。

[リスト3]テーマを適用する
import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import lightBlue from '@material-ui/core/colors/lightBlue';
import teal from '@material-ui/core/colors/teal';
import AppBar from '@material-ui/core/AppBar';
import Button from '@material-ui/core/Button';
import Container from '@material-ui/core/Container';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';

const theme = createMuiTheme({ // (1)
  palette: {
    primary: {
      main: lightBlue[800], // (3)
    },
    secondary: {
      main: teal[200], // (4)
    }
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>{/* (2) */}
      <AppBar position="static" color="primary">{/* (5) */}
        <Toolbar>
          <Typography variant="h6">サンプル</Typography>
        </Toolbar>
      </AppBar>
      <Container>
        <Button variant="contained" color="secondary">{/* (6) */}
          Hello World
        </Button>
      </Container>
    </ThemeProvider>
  );
}

export default App;

 テーマは(1)のようにcreateMuiTheme関数で作成します。作成したtheme変数を(2)のように<ThemeProvider>コンポーネントに渡して、他のMaterial-UIのコンポーネントを包むことで、テーマを適用します。色は(3)と(4)のように設定しています。

 今回は(5)で<AppBar>(ヘッダー)を使ってみました(後編で解説します)。こちらは色をprimaryに設定したので、`lightBlue[800]の色になります。また、ボタンの色はsecondaryに設定したので、teal[200]^^の色になります。それでは実際にどうなったか見てみましょう(図8)。

図8:ヘッダーとボタンがテーマの色になった
図8:ヘッダーとボタンがテーマの色になった

 それらしい色になりました。このように、テーマで色を指定することで、統一感のあるUIを容易に構築できます。

Boxの例

 それでは、もう少し実例を見てみましょう。Boxコンポーネントで領域を区切って、簡単なレイアウトを組んでみます(リスト4)。

[リスト4]Boxの例
// 略
import Box from '@material-ui/core/Box';

function App() {
  return (
    {/* (略) */}
      <Container>
        <Box style={{ display: 'flex', flexDirection: 'row' }}>{/* (1) */}
          <Box width={1/4} style={{ padding: '8px' }} border={1}>{/* (2) */}
            <Button
              variant="contained"
              color="secondary"
              style={{ width: '100%' }}
            >
              ボタン1
            </Button>
          </Box>
          <Box width={1/2} style={{ padding: '8px' }} border={1}>{/* (3) */}
            <Button
              variant="contained"
              color="secondary"
              style={{ width: '100%' }}
            >
              ボタン2
            </Button>
          </Box>
          <Box width={1/4} style={{ padding: '8px' }} border={1}>{/* (2) */}
            <Button
              variant="contained"
              color="secondary"
              style={{ width: '100%' }}
            >
              ボタン3
            </Button>
          </Box>
        </Box>
      </Container>
    {/* (略) */}
  );
}

export default App;

 まずは(1)で横方向のFlexboxを定義します。そして、 widthの値を1/4にした(2)と、1/2にした(3)を並べてみました。直感的には1:2:1の比になりそうな指定ですね。実際に動かしてみると、表示は図9のようになります。

図9:1:2:1になった
図9:1:2:1になった

 1:2:1の比になりました。Boxをはじめとしたレイアウトに関するコンポーネントでは、widthやheightに割合を指定でき、親(ここでは(1)のBox)の幅に対して割合に応じた幅を持つことができます。

Menuの例

 最後に、ナビゲーションのジャンルから、Menuコンポーネントの例を挙げてみます。ボタンを押すとメニューが開いて、選択すると閉じる、という簡単なものです(リスト5)。

[リスト5]Menuの例
function MenuSample() {
  const [anchorEl, setAnchorEl] = useState(null);

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget); // (4)
  };

  const handleClose = () => {
    setAnchorEl(null); // (5)
  };

  return (
    <Box>
      <Button
        variant="contained"
        color="secondary"
        onClick={handleClick}
      >
        メニューを開く
      </Button>
      <Menu // (2)
        id="simple-menu"
        anchorEl={anchorEl} // (1)
        open={Boolean(anchorEl)} // (3)
        onClose={handleClose}
      >
        <MenuItem onClick={handleClose}>アイテム1</MenuItem>
        <MenuItem onClick={handleClose}>アイテム2</MenuItem>
        <MenuItem onClick={handleClose}>アイテム3</MenuItem>
      </Menu>
    </Box>
  );
}

 Menuコンポーネントの表示位置は(1)でanchorEl属性に設定したDOM要素からの相対位置で決定されます。そのため、JSX内ではどこに記述しても構いませんが、管理上の扱いやすさから、anchorElに設定する要素から近い場所に記述する慣例があります。今回の例では、(2)のようにButtonの真下に記述しました。

 (3)のopen属性にtrueを与えると、メニューが表示されます。ボタンのクリック時に(4)のように取得した要素を、(3)で真偽値に変換してからopen属性に渡すことで「ボタンクリックでメニューを表示」という挙動を実現しています。逆に閉じるときは、MenuItemやメニュー外をクリックした際に呼び出されるhandleClose関数内で(5)の処理をすることで、(3)に渡る値をfalseにしています。なお、開閉状態の管理と要素の管理は別々に行っても問題ありません。

まとめ

 今回はMaterial-UIの解説の前編でした。Webサイトやアプリを組み上げていくために必要な部品が初めからそろっている中で開発するのは楽しいですね。次回は引き続き、Material-UIについて解説します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
現場で役立つ! React向けライブラリ詳説連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/14322 2021/06/14 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング