それ Bootstrap でやればええんやで?


この記事は WESEEK Advent Calendar 2020 12日目の記事です。

前提

  • 現在 GROWI を開発中
  • GROWI とは? 極端に User first な wiki です。
  • Top page はこんな感じ。

結論

  • なんでもプログラマブルにしなくても Bootstrap が simple に解決してくれる。
  • Bootstrap 4.5

経緯

  • 新 version のリリースで大幅にデザインを変更した。
  • mobile 版に対応するために、<PageAccessories /> というコンポーネントの配置に苦戦した。(以下のやつ)

  • これは responsive 対応しておらず、mobile 版にすると・・・

  • これは新バージョンで色々な機能(ページリスト/タイムライン/更新履歴/添付データ/共有リンク) を としてまとめた。

  • しかし、それが mobile 版では表示されず、この便利な機能が使いにくいというのは、User first ではない。

  • なので、mobile 版でも <PageAccessories /> を表示するのが今回の task だった。

  • すぐ終わると思っていた。

案1 同じのつこたろ!

Reviewer に秒殺された。

  • 理由は このコンポーネントの処理は結構重たいので、複数使うのはイケていない。
    • 実はこの <PageAccessories /> は <PageAccessoriesModal /><PageAccessoriesModalControl /> という2つのコンポーネントを内包している。
    • さらに <PageAccessoriesModdl /> には、4つの重たいコンポーネントが内包されているため、複数このコンポーネントを使うのは Not Good.

案2 バラしたろ!

  • <PageAccessories /> 単体で処理できたらいいのだが、パッとできなかった。
  • <PageAccessories /> には <PageAccessoriesModal /> と <PageAccessoriesModalControl /> を含んでいる。
  • このコンポーネントをバラして、重たい処理である <PageAccessoriesModal /> を1つにすればええやん ?
  • つまり、2つの <PageAccessoriesModalControl /> を使い 1つの <PageAccessoriesModal /> を使う。

しかし、ここで配置に相当苦戦した。
具体的には、以下の内容である。

  • User page の場合

    • ユーザー情報を一番上に配置せねばならず、その条件分岐がいる。
    • 新しくできた <PageAccessories /> を User 仕様にするために条件分岐しなければいけない。
  • User page の図

    • lg 以上のとき
    • mg 以下のとき
  • 普通の page のとき

    • lg 以上のとき
    • mg 以下のとき

理想とした配置はこんな感じである。(この図は GROWI の draw.io で作成。)

- 以下は実際のコード

return (
    <>
      <TabContent activeTab={editorMode}>
        <TabPane tabId="view">
          <div className="d-flex d-md-none justify-content-end border-bottom">  // md までは非表示 
            <PageAccessoriesModalControl                                        // 1つ目
              isGuestUser={isGuestUser}
              isSharedUser={isSharedUser}
            />
          </div>
          <div className="d-flex flex-row justify-content-around">              // 子要素を横並び 
            <div className="w-100">
              {pageUser && <UserInfo pageUser={pageUser} />}             // ここは jxs で条件分岐
              <Page />
            </div>
            <div className="d-none d-md-block grw-side-contents-container">     // 基本非表示 md以上で表示
              <div className="grw-side-contents-sticky-container">
                <PageAccessoriesModalControl                                    // 2つ目
                  isGuestUser={isGuestUser}
                  isSharedUser={isSharedUser}
                />
                <div id="revision-toc" className="revision-toc">
                  <TableOfContents />
                </div>
                {pageUser && <UserContentsLinks />}                              // ここも jxs で条件分岐
              </div>
            </div>
          </div>
          <PageAccessoriesModal                                                  //重たい処理はまとめた
            isGuestUser={isGuestUser}
            isSharedUser={isSharedUser}
            isOpen={isPageAccessoriesModalShown}
            onClose={closePageAccessoriesModal}
          />
        </TabPane>
        .
        .
    </>
  );
};

リファクタや調整などを行い,
午前 3 時にこの形に辿り着いたとき、勝ちを確信した。

確信しただけだった。

案3 Bootstrap でやれば?

  • 上の案はさっきも書いたのだが、2つの<PageAccessoriesModalControl /> というコンポーネントを使い、1つの重たいコンポーネントを共通化するというものだった。
  • しかし、 1つの <PageAccessoriesModalControl /> と 1つの <PageAccessoriesModal /> つまり最初に戻ってしまうが、<PageAccessories /> で同じことができることが一番の理想である。

完成形 ( これ以外のファイルも変更しているが大枠は以下の通り )


  return (
    <>
      <TabContent activeTab={editorMode}>
        <TabPane tabId="view">
          <div className="d-flex flex-column flex-lg-row-reverse">  // 基本的に縦並び, lg 以上で横並びにする 
            <div className="grw-side-contents-container"> 
              <div className="grw-side-contents-sticky-container">
                <div className="border-bottom pb-1">
                  <PageAccessories />
                </div>
                <div className="d-none d-lg-block">                 // 基本的には表示しない、lg 以上で表示する
                  <div id="revision-toc" className="revision-toc">
                    <TableOfContents />
                  </div>
                  {pageUser && <UserContentsLinks />}               // ここは jsx 記法で条件分岐
                </div>
              </div>
            </div>
            <div>
              {pageUser && <UserInfo pageUser={pageUser} />}        // ここも
              <Page />
            </div>
          </div>
  • 図で Before / After を見ると...
  • Before
  • After

『はぇ~』ってなったところ

  • flex-column / row の駆使する。
  • size (md や lg) などで いつ表すか(block)で余計な条件分岐がいらなくなる。
  • reverse するという発想。

※この記事は WESEEK Tips wiki に 2020/12/5 に投稿された記事の転載です。
Tips wiki では、IT企業の技術的な情報やプロジェクトの情報を公開可能な範囲で公開してます。