Motomichi Works Blog

モトミチワークスブログです。その日学習したことについて書いている日記みたいなものです。

@mui/baseのコンポーネントにstyled-jsxでスタイル適用をしてみる

参照したページ

はじめに

スタイルが適用されていないヘッドレスなUIライブラリが流行ってきているみたいなので、ちょっと @mui/base を使ってみます。

2023年4月17日現在では、まだ @mui/base はalpha版しか無いようです。

そのまま使ってみる

試しに Unstyled React Switch component and hook - Base UI を使ってみました。

そのまま使うと全くスタイルが適用されていないプレーンなチェックボックスでした。

スタイルを適用してみる

試しにSwitchコンポーネント( Unstyled React Switch component and hook - Base UI )にスタイル適用をしてみます。

disabledに固定値でfalse入れていたり、CSSはテキトーに書いているだけですが、styled-jsxを使う場合は以下のような感じで書けそうです。

import { ChangeEvent, useState } from 'react';
import css from 'styled-jsx/css';
import SwitchUnstyled, {
  switchUnstyledClasses,
} from '@mui/base/SwitchUnstyled';

export function MySwitch() {
  const [isChecked, setIsChecked] = useState(true);

  const slotProps = {
    root: { className: `root ${className}` },
    thumb: { className: `thumb ${className}` },
    track: { className: `track ${className}` },
    input: { className: `input ${className}` },
  };

  const onChange = (event: ChangeEvent<HTMLInputElement>) => {
    console.log('event.target.value: ', event.target.value);
    console.log('event.target.checked: ', event.target.checked);
    setIsChecked(event.target.checked);
  };

  return (
    <>
      <SwitchUnstyled
        slots={{ root: 'label' }}
        slotProps={slotProps}
        checked={isChecked}
        disabled={false}
        onChange={onChange}
      />
      {styles}
    </>
  );
}

const { className, styles } = css.resolve`
  .root {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 24px;
  }

  .track {
    position: relative;
    width: 46px;
    height: 12px;
    cursor: pointer;
    background-color: #ccc;
    border: none;
    border-radius: 12px;
  }

  .root.${switchUnstyledClasses.checked} .track {
    background-color: #00f;
  }

  .root.${switchUnstyledClasses.disabled} .track {
    background-color: #eee;
  }

  .thumb {
    position: absolute;
    top: 1px;
    right: auto;
    left: 0;
    width: 20px;
    height: 20px;
    cursor: pointer;
    background: #fff;
    border: 1px solid #bcbdbd;
    border-radius: 100%;
  }

  .root.${switchUnstyledClasses.checked} .thumb {
    right: 0;
    left: auto;
  }

  .root.${switchUnstyledClasses.disabled} .thumb {
    background-color: #f5f5f5;
  }

  .input {
    position: absolute;
    z-index: -1;
  }
`;

おわりに

実質CSSを書くだけでSwitchのコンポーネントができるので、フィールドの振る舞いから自分で書くのに比べたらだいぶ楽に感じました。