material-table で行を選択した際のチェックボックスとツールバーの色をカスタマイズする

はじめに

テントの中から失礼します、IoT 事業部のてんとタカハシです!

material-table では、行を選択可能とするオプションが存在します。行を選択した際、チェックボックスとツールバーに色が着くのですが、その色をカスタマイズする方法について確認してみました。

環境

環境は下記の通りです。

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H2

% node --version
v14.7.0

% yarn --version
1.22.10

% create-react-app --version
4.0.3

% yarn list --depth=0 | grep -e @material-ui/core -e material-table
├─ @material-ui/core@4.11.4
├─ material-table@1.69.3

デフォルトの行選択可能なテーブル

まずは、行が選択可能なテーブルのデフォルト状態を確認します。

例として、ユーザーの一覧を表示するテーブルを実装します。options の selection をtrueにすることで、行を選択することが可能になります。

App.tsx

import UserListTable from './components/UserListTable';

const App = () => {
  const userList = [
    {
      userId: '0001',
      username: '矢沢 孝宏',
      age: 29,
      birthday: '09/04',
    },
    {
      userId: '0002',
      username: '楠本 茉莉',
      age: 22,
      birthday: '03/26',
    },
    {
      userId: '0003',
      username: '前島 桃桜',
      age: 20,
      birthday: '09/27',
    },
    {
      userId: '0004',
      username: '甲斐 竜太',
      age: 25,
      birthday: '08/13',
    },
    {
      userId: '0005',
      username: '麻生 武司',
      age: 33,
      birthday: '02/14',
    },
  ];

  return (
    <div style={{ padding: 40 }}>
      <UserListTable data={userList} />
    </div>
  );
};

export default App;

components/UserListTable.tsx

import MaterialTable from 'material-table';

type User = {
  userId: string;
  username: string;
  age: number;
  birthday: string;
};

type Props = {
  data: User[];
};

const UserListTable: React.FC<Props> = (props) => {
  const { data } = props;

  const columns = [
    {
      title: 'ユーザーID',
      field: 'userId',
    },
    { title: 'ユーザー名', field: 'username' },
    {
      title: '年齢',
      field: 'age',
    },
    {
      title: '誕生日',
      field: 'birthday',
    },
  ];

  return (
    <MaterialTable
      title={'ユーザー一覧'}
      options={{
        selection: true, // ★ 行選択可能
      }}
      columns={columns}
      data={data}
    />
  );
};

export default UserListTable;

ブラウザで表示すると、このようなテーブルになります。行の左側にチェックボックスが表示されていますね。

行を選択すると、チェックボックスとツールバーが赤色に変わります。この色を変更していきます。

一括で色を変更する

Material-UI のテーマカラーを変更することで、チェックボックスとツールバーの色を一括で変更することができます。どちらもセカンダリーの色を適用する挙動となっていますので、ここでは色を緑に変更した場合の表示を確認してみます。

App.tsx

import * as colors from '@material-ui/core/colors';
import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';

import UserListTable from './components/UserListTable';

const theme = createMuiTheme({
  palette: {
    secondary: {
      main: colors.green[700],
    },
  },
});

const App = () => {
  const userList = [
    ...
  ];

  return (
    <ThemeProvider theme={theme}>
      <div style={{ padding: 40 }}>
        <UserListTable data={userList} />
      </div>
    </ThemeProvider>
  );
};

export default App;

ブラウザで表示すると、チェックボックス、ツールバーどちらも緑色に変わっていることが確認できます。

ヘッダーのチェックボックスのみ色を変更する

一括で変更するのではなく、個別で変更したい場合の対応方法について確認します。

テーブルヘッダーのチェックボックスのみ色を変更したい場合は、options のheaderSelectionPropsで他のテーマカラーを指定することができます。ここでは、プライマリーの色を指定します。

components/UserListTable.tsx

...

const UserListTable: React.FC<Props> = (props) => {
  const { data } = props;
  
  ...

  return (
    <MaterialTable
      title={'ユーザー一覧'}
      options={{
        selection: true,
        headerSelectionProps: {
          color: 'primary',
        },
      }}
      columns={columns}
      data={data}
    />
  );
};

export default UserListTable;

ブラウザで表示すると、テーブルヘッダーのチェックボックスが青色に変わっていることが確認できます。

material-table のソースコードを確認してみると、

指定した headerSelectionProps の値が Material-UI の Checkbox コンポーネントに渡されています。

components/m-table-header.js

...

<Checkbox
  indeterminate={
    this.props.selectedCount > 0 &&
    this.props.selectedCount < this.props.dataCount
  }
  checked={
    this.props.dataCount > 0 &&
    this.props.selectedCount === this.props.dataCount
  }
  onChange={(event, checked) =>
    this.props.onAllSelected && this.props.onAllSelected(checked)
  }
  {...this.props.options.headerSelectionProps}    // ★
/>

...

ボディのチェックボックスのみ色を変更する

テーブルボディのチェックボックスのみ色を変更したい場合は、options のselectionPropsで他のテーマカラーを指定することができます。ここでは、プライマリーの色を指定します。

components/UserListTable.tsx

...

const UserListTable: React.FC<Props> = (props) => {
  const { data } = props;
  
  ...

  return (
    <MaterialTable
      title={'ユーザー一覧'}
      options={{
        selection: true,
        headerSelectionProps: {
          color: 'primary',
        },
        selectionProps: () => ({
          color: 'primary',
        }),
      }}
      columns={columns}
      data={data}
    />
  );
};

export default UserListTable;

ブラウザで表示すると、テーブルボディのチェックボックスが青色に変わっていることが確認できます。

material-table のソースコードを確認してみると、

こちらも指定した selectionProps の値が Material-UI の Checkbox コンポーネントに渡されています。

components/m-table-body-row.js

...

  renderSelectionColumn() {
    let checkboxProps = this.props.options.selectionProps || {};

    ...

    return (
      <TableCell
        size={size}
        padding="none"
        key="key-selection-column"
        style={{ width: selectionWidth }}
      >
        <Checkbox
          size={size}
          checked={this.props.data.tableData.checked === true}
          onClick={(e) => e.stopPropagation()}
          value={this.props.data.tableData.id.toString()}
          onChange={(event) =>
            this.props.onRowSelected(event, this.props.path, this.props.data)
          }
          style={styles}
          {...checkboxProps}
        />
      </TableCell>
    );
  }

...

ツールバーのみ色を変更することはできなそう

ツールバーの色を個別で指定するための option を探してみたのですが見当たりませんでした。

material-table ソースコードを確認すると、

Toolbar の className は、行が選択されている状態だとhighlightが適用されるようです。

src/components/m-table-toolbar.js

<Toolbar
  className={classNames(classes.root, {
    [classes.highlight]:                   // ★
      this.props.showTextRowsSelected &&
      this.props.selectedRows &&
      this.props.selectedRows.length > 0,
  })}
>
  {title && this.renderToolbarTitle(title)}
  {this.props.searchFieldAlignment === "left" && this.renderSearch()}
  {this.props.toolbarButtonAlignment === "left" && this.renderActions()}
  <div className={classes.spacer} />
  {this.props.searchFieldAlignment === "right" && this.renderSearch()}
  {this.props.toolbarButtonAlignment === "right" && this.renderActions()}
</Toolbar>

この highlight のスタイルを確認すると、ライト/ダークモードで適用されるテーマカラーが直接指定されています。よって、ここを何かしらの方法で書き換えることは想定されてないように見えます。

src/components/m-table-toolbar.js

export const styles = (theme) => ({
  root: {
    paddingRight: theme.spacing(1),
  },
  highlight:
    theme.palette.type === "light"
      ? {
          color: theme.palette.secondary.main,                            // ★
          backgroundColor: lighten(theme.palette.secondary.light, 0.85),  // ★
        }
      : {
          color: theme.palette.text.primary,
          backgroundColor: theme.palette.secondary.dark,
        },

おわりに

material-table で行を選択した際のチェックボックスとツールバーの色をカスタマイズする方法について確認してみました。こういった細かいカスタマイズは、公式のドキュメントを見るだけでは、なかなか対応が難しかったりするので、ソースコードを直接読んで挙動を理解しちゃった方が早いですね。

今回は以上になります。最後まで読んで頂きありがとうございました!