material-tableでソート矢印アイコンをユーザーに認識されやすいようにカスタマイズしてみた

2020.08.10

こんにちは、CX事業本部の若槻です。

今回は、以前の記事で作成したReact + Material-UI + material-tableのアプリで、material-tableのテーブルデータのソート矢印アイコンをアプリユーザーに認識されやすいようにカスタマイズしてみました。

解決したいこと

material-tableでは列タイトル横の矢印をクリックすると、その列の値をもとにテーブルデータをソートできます。しかしこの矢印は既定(ページを読み込んだ直後の時点)では非表示で、表示されるのはマウスオーバー時やソートがアクティブな時のみです。また色がタイトル文字と同じグレーであるため、アプリユーザーからしたらパッと見でソート操作が出来ることに気付きにくいです。

よって、このソート矢印を目立たせてソート操作ができることをアプリユーザーに認識されやすくしたいです。 スクリーンショット_2020-08-10_18_04_39.png

アウトプット

商品ページを開くと既定でソート矢印アイコンが表示されるようにし、またアイコンの色も青色としました。 material-table.gif

設定した内容

商品ページProductPage.tsxのmaterial-tableのソート矢印に対して以下のような設定を行ってみました。

  • 既定(ページを読み込んだ直後の時点)で表示されるようにする
  • スタイルのカスタマイズ

ソート矢印が既定で表示されるようにする

下記のように<MaterialTable>コンポーネントのcolumsn属性で特定の列にdefaultSortを指定すれば、その列は既定でソートがアクティブとなり、矢印も既定で表示されるようになります。

      <MaterialTable
        columns={[
          { 
            title: '商品名',
            field: 'itemName',
            defaultSort: 'asc'
          },
          { title: 'カテゴリー', field: 'category' },
          { title: '重量(g)', field: 'weight' },
          { title: '価格(円)', field: 'price' },
        ]}
 〜〜〜〜〜〜〜〜〜
      />

今回は商品名列をascでソートさせましたが、日付や日時を示す列があればその列をdesc(最近順)としても良いかもしれません。

ソート矢印のスタイルをカスタマイズする

ソート矢印のスタイルをカスタマイズしたい場合は、<MaterialTable>コンポーネントのicons属性を使用します。

Material-UIのライブラリのコンポーネントを使うのでインポートします。

import {ArrowUpward} from '@material-ui/icons';
import * as colors from "@material-ui/core/colors";

<MaterialTable>コンポーネントに次のようにicons属性を追加します。

      <MaterialTable
        icons={{
          SortArrow: React.forwardRef((props, ref) => 
            <ArrowUpward
              {...props} ref={ref} style={{ color: colors.blue[800] }}
            />
          ),
        }}
 〜〜〜〜〜〜〜〜〜
      />

ArrowUpwardはmaterial-uiで用意されている上向き矢印アイコンです。インポートした<ArrowUpward/>コンポーネントにstyle属性を指定してスタイルをカスタマイズしています。今回はcolorsによりMaterial-UIで用意された色を使用して文字色を変更しています。style以外のpropsおよびrefReact.forwardRef()を使用して上位の<MaterialTable>のものを適用しています。こうして作成した<ArrowUpward/>SortArrowに指定することによりソート矢印をカスタマイズしています。

上記2つの変更後の商品ページProductPage.tsxは次のようになりました。

import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import MaterialTable from 'material-table';
import GenericTemplate from '../templates/GenericTemplate';
import {ArrowUpward} from '@material-ui/icons';
import * as colors from "@material-ui/core/colors";

type Props = {} & RouteComponentProps<{}>;

const ProductPage: React.FC<Props> = (props) => {
  return (
    <GenericTemplate title={'商品ページ'}>
      <MaterialTable
        icons={{
          SortArrow: React.forwardRef((props, ref) => 
            <ArrowUpward
              {...props} ref={ref} style={{ color: colors.blue[800] }}
            />
          ),
        }}
        columns={[
          { 
            title: '商品名',
            field: 'itemName',
            defaultSort: 'asc'
          },
          { title: 'カテゴリー', field: 'category' },
          { title: '重量(g)', field: 'weight' },
          { title: '価格(円)', field: 'price' },
        ]}
        data={[
          { itemName: 'チョコレート', category: 'お菓子', weight: 100, price: 120 },
          { itemName: 'ケーキ', category: 'お菓子', weight: 400, price: 480 },
          { itemName: 'りんご', category: 'フルーツ', weight: 500, price: 360 },
          { itemName: 'バナナ', category: 'フルーツ', weight: 200, price: 300 },
          { itemName: 'みかん', category: 'フルーツ', weight: 250, price: 180 },
        ]}
        options={{
          showTitle: false,
        }}
      />
    </GenericTemplate>
  );
};

export default withRouter(ProductPage);

おわりに

material-tableでテーブルデータのソート矢印アイコンをアプリユーザーに認識されやすいようにカスタマイズしてみました。

アプリユーザー視点でフロントエンドのUI/UXを考えて改善を行うのは簡単なようで難しいですが、やってみるとなかなか楽しいですね。

参考

以上