🖥️

React-Splitを使って画面分割を実現する

2022/02/15に公開

目的

ここではReactで画面分割し、分割した画面の幅をマウスで調整できるようにすることを目的とします。

使用するライブラリ

React-Splitをとにかく使ってみる

公式に記載の通り、分割したいコンポーネントをSplitコンポーネントの子コンポーネントに配置することで、いい感じに画面を分割してくれます(もちろんマウスでの幅調整も可能です)。インポートするコードサイズが小さい上、Typescript対応してくれているのも使いやすくて良いですね😊

import Split from "react-split";

const menuItems = [
  { label: "メニュー1", url: "#1" },
  { label: "メニュー2", url: "#2" },
  { label: "メニュー3", url: "#3" },
  { label: "メニュー4", url: "#4" }
];

export default function App() {
  return (
    <Split className="flex" sizes={[25, 75]}>
      {/** 一つ目のコンポーネント */}
      <ul className="bg-stone-50 p-2">
        {menuItems.map((item) => (
          <li key={item.url}>
            <a href={item.url}>{item.label}</a>
          </li>
        ))}
      </ul>
      {/** 二つ目のコンポーネント */}
      <div className="bg-indigo-50 flex items-center justify-center">
        コンテンツ
      </div>
    </Split>
  );
}

さらにこだわってみる

上記だけでも概ねやりたいことは叶っていますが、アニメーションやガターの見栄えを変えたいなど、状況によってカスタマイズしたいケースはあるかと思います。今回は特に以下のカスタマイズに対応したいと思います。

  • ガターの色を変更する
  • ガターをマウスホバー時に拡大する

1.デフォルトのガタースタイルを無効化

まず少々トリッキーですが、デフォルトのガター幅(=10px)が適用されないように空のカスタムスタイルを設定します。この設定は後にガターのカスタムエレメントに、class指定でスタイルを適用したいために実施します。

 <Split
      className="flex"
+      // デフォルトのガター幅を無効にするために指定
+      gutterStyle={() => ({})}
      sizes={[25, 75]}
    >

2. カスタムスタイルの適用

次に、ガターのスタイルをカスタマイズするためにgutterプロパティにてカスタムエレメントを設定します。gutterプロパティにはHTMLElementを返す関数を指定する必要があり、ここでgutterエレメントに独自スタイルを適用していきます。

    <Split
      className="flex"
+      gutter={() => {
+        const gutterElement = document.createElement("div");
+        // ガター幅、ホバー時の挙動、アニメーションを指定
+        // ※tailwindcssのクラスについては別途公式等参照ください
+        gutterElement.className = `w-[2px] bg-indigo-500 hover:cursor-col-resize hover:w-4 hover:border-x hover:bg-indigo-700 transition-all delay-300 duration-300 ease-in-out`;
+        return gutterElement;
+      }}
      // デフォルトのガター幅を無効にするために指定
      gutterStyle={() => ({})}
      sizes={[25, 75]}
    >

tailwindcssを使うとこういったHTMLエレメントにも、テーマのスタイルの適用が容易になりますね。

全体のコード

👉最終的なコードと結果は次のようになります。

import Split from "react-split";

const menuItems = [
  { label: "メニュー1", url: "#1" },
  { label: "メニュー2", url: "#2" },
  { label: "メニュー3", url: "#3" },
  { label: "メニュー4", url: "#4" }
];

export default function App() {
  return (
    <Split
      className="flex"
      gutter={() => {
        const gutterElement = document.createElement("div");
        gutterElement.className = `w-[2px] bg-indigo-500 hover:cursor-col-resize hover:w-4 hover:bg-indigo-700 transition-all delay-300 duration-300 ease-in-out`;
        return gutterElement;
      }}
      // デフォルトのガター幅を無効にするために指定
      gutterStyle={() => ({})}
      sizes={[25, 75]}
    >
      <ul className="bg-stone-50 p-2">
        {menuItems.map((item) => (
          <li key={item.url}>
            <a href={item.url}>{item.label}</a>
          </li>
        ))}
      </ul>
      <div className="bg-indigo-50 flex items-center justify-center">
        コンテンツ
      </div>
    </Split>
  );
}

最後に

React-Splitは導入の敷居が低く、本記事で紹介した以外にもカスタマイズ性が豊富なためオススメです。最後に、本記事で紹介したコードはcodesandboxにも公開していますので、よければご参考ください。
https://codesandbox.io/s/cool-mountain-jf8br?file=/src/App.tsx

Discussion