Umi Uyuraのブログ

Titaniumを使ったスマートフォンアプリ開発を中心に、プログラミング関連の作業ログ。

React + NW.jsにデザインフレームワークとしてMaterial UIを組み合わせてみた

私はデザインセンスがかけらもないので、UI部分については、どうしても素っ気ないものになってしまいます。

最近取り組んでいるReact + NW.jsですが、そのまま作ると素のHTML要素が並ぶことになるので、せめて基本的なコンポーネントくらいは見栄えを良くできないと、何かデザインフレームワークを使ってみることにしました。

探してみると、 Material UI という、Reactベースでマテリアルデザインのフレームワークを見つけたので、以前から作っていたReact + NW.jsのサンプル( umi-uyura/react-on-nwjs-sample )をベースに、Material UIを適用してみることにしました。

※2015/05/26追記

これを書いたタイミングではMaterial UIのバージョンは0.7.5だったのですが…

ということになりましたので、本エントリは参考レベルとしてください。

大きな違いとしては、CSSがLESSをやめてインラインJavaScript方式になっていたりします。

ただ、現時点では若干不具合もあるようなので、検証しながら採用していただくのが良いかと思います。

※2015/06/22追記

Inline Style版に対応してみました。

umi-uyura.hatenablog.com

前提条件

Browserify + Reactify

Material UIは、依存関係の解決とJSXの変換のために、BrowserifyとReactifyを使うようです。

これは、先日使ってみたのでOK。

umi-uyura.hatenablog.com

CSSフレームワーク

CSSフレームワークとして、LESSを採用しているようです。

Sassの方が良い人には gpbl/material-ui-sass に.scssバージョンがあります。

Stylus用の Autarc/material-ui-stylus もあるようなのですが、こちらは対応バージョンが少し古い0.5.0で、最新の0.7.5に対応していないようでした。

私はLESSやSassは使ったことがなく、Stylusの方が馴染みがあったので、こちらを採用しようと思ったのですが、断念しました。

React-Tap-Event-Plugin

用意されているいくつかのコンポーネントは、タッチイベント処理のために zilverline/react-tap-event-plugin を使っているようです。

これは一時的な対処らしく、Reactが1.0になったときに削除される予定らしいです。

インストール

Material UIとLESSをプロジェクトにインストールします。

$ npm install material-ui less --save

実装

React-Tap-Event-Pluginの組み込み

いずれ削除される予定のReact-Tap-Event-Pluginですが、Reactが1.0になるまでは必要とのことなので、これを組み込みます。

アプリの開始時に以下のコードを呼び出しておくとのことだったので、最初のReactの読み込み直後に追加しました。

app.jsx

var React = require('react');
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();

Robotoフォントの組み込み

Material UIは Robotoフォント を指定しているようなので、フォントの読み込みをindex.htmlへ追加します。

このリンク 先に表示される 3. Add this code to your website: から、Standard なHTMLの <link> タグ方式で、 <head> タグ内に追加しました。

index.html

...
<head>
  <title>React on NW.js with Material UI</title>
  <link href='http://fonts.googleapis.com/css?family=Roboto:400,300,500' rel='stylesheet' type='text/css'>
  ...
</head>
...

コンポーネントの組み込み

練習用に、「押したらalertを表示するボタン」コンポーネントを、Maternal UIのコンポーネントを作ってみました。

Hi.jsx

'use strict';

var React = require('react');
var MUI = require('material-ui');

var RaisedButton = MUI.RaisedButton;

var Hi = React.createClass({
  doClick: function() {
    alert('Hi !');
  },
  render: function() {
    return (
      <RaisedButton label="Hi" primary={true} onClick={this.doClick} />
    );
  }
});

module.exports = Hi;

require('material-ui') で読み込んだMaterial UIオブジェクトから、今回使う RaisedButton コンポーネントを読み込んでいます。

これでRaisedButtonが使えるようになるので、あとは ドキュメント を参考にしつつ、ボタンのラベル属性( label )とクリックイベントハンドラなどをセットしています。

CSS(LESS)の組み込み、およびカスタマイズ

Material UIのCSSを適用するために、Material UIのパッケージ内にある src/less/components.lesssrc/less/scaffolding.less を読み込みます。

この2ファイルを読み込むために、 style/bundle.less を用意して、以下のように読み込ませました。

mui.less

@import "../node_modules/material-ui/src/less/scaffolding.less";
@import "app.less";
@import "../node_modules/material-ui/src/less/components.less";

2つの間に入っている app.less はアプリ独自のスタイルを定義するためのもので、Material UIコンポーネントのデザインをカスタマイズしたい場合は、このように scaffolding.lesscomponents.less の間で読み込むことでできるようです。

これを lessc コマンドでコンパイルしたものを、index.html内で読み込ませることにしました。

$ $(npm bin)/lessc style/bundle.less build/bundle.css

index.html

<link rel="stylesheet" type="text/css" href="build/bundle.css" />

実行

こんな感じで作ったものを実行すると、それっぽいデザインが反映されていました。

f:id:umi-uyura:20150524212310p:plain

できたもの。

umi-uyura/react-nwjs-materialui-sample

まとめ

LESSのコンパイルについては、初めはBrowserifyでまとめてできないかと思い、 wilson428/node-lessifycapaj/require-stylify を試してみたのですが、そもそもLESS自体を使ったことがなかったせいか、パラメータの設定がよくわからず、うまく動かせませんでした。

やはりGulpなどのタスクランナーと組み合わせている事例が多いのですが、それをやりだすと npm run-script で動かしてみるもの全てを見直したくなりそうだったので、今回は素直に lessc コマンドでコンパイルしています。

参考