Open9

2023年 UI1グランプリ【THE FINAL】

t_keshit_keshi

このスクラップでは、どのようなケースでどのようなUIライブラリを使うのが、ベストな選択なのか、雑にまとめていきます。

大会風に書いているのはあくまでノリであって、ベストな選択は状況によって結論は異なります。
ナンバーワンを決めるのは不可能なことは重々承知です。

全く使ったことのないライブラリについても紹介しているため、どうしても情報に誤りがあったり、大事な情報が欠けていたりもするかと思います。
知見のある方に訂正や補足をいただければと思い、スクラップ形式にしてみました。

「UIライブラリの技術選定に関する知見がたまるスクラップ」という感じにしたいです。
ご紹介したもの以外にも有力なライブラリがあるかもしれませんし、お気軽にコメントください🙏

t_keshit_keshi

EntryNo.0381 MUI

https://mui.com/

観客投票では圧倒的人気ぃぃぃ〜
彼らはゆぅぅぅ〜う、「我らがマテリアルデザインの体現者」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

MUIのメリット

  • コンポーネントの豊富さは◎
  • ドキュメント充実
  • 知名度が高く、使用経験のある人が多い
  • コンポーネントのデフォルトのpropsを変更できるなど、カスタマイズの手段が多い
  • スタイルエンジン(emotion, styled-componentなど)を選べる
  • マテリアルデザインを簡単に実現できる

MUIのデメリット

  • デザインがマテリアルデザインを踏襲していない場合には、カスタマイズが大変になる
  • fieldsetをネストしたInput系のコンポーネントなど、知見がないとカスタマイズは難しいこともある

コメント

いやぁ〜、さすがでしたね、昨年の覇者としての風格を見せつけたというか、そんな印象でした。
ネタも進化していて、JSSをデフォルトのスタイルエンジンにするのは止めたようです。
パフォーマンスの面で、それはとても良い決断だったと思います。

近年のUnstyled化、ロジック部分と見た目部分との分離を進めていく方向性もうまく進んでいるようで、今後も期待できるライブラリです。

ただ一方で、CSS-in-JSの知見がなく、マテリアルデザインと大きく異なるデザインをMUIで表現しようとすると、どうしても実装の労力が高く感じてしまう場合があります。
その点は、注意が必要ですね。

スタイルエンジンが選べるのは、人によってはメリットと感じるかもしれないですが、emotionstyled-componentの書き味の違いは大きくないですし、特にこだわりがなければどちらでも良いのかもしれません。

参考記事

https://zenn.dev/yumemi_inc/articles/2021-09-26-material-ui-v5

t_keshit_keshi

EntryNo.2093 ChakraUI

https://chakra-ui.com/

あの人気漫画ぁぁぁ、『NARUTO』のチャクラに由来する、ライブラリぃぃぃ〜
カスタマイズのしやすさでは、「圧倒的実力を誇る」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

ChakraUIのメリット

  • コンポーネントの豊富さは○
  • ドキュメント充実
  • 型安全にカスタマイズが可能
  • 便利なカスタムフックも同梱
  • Chakra Factoryのおかげで、自分でコンポーネントを足す場合にも非常に楽

ChakraUIのデメリット

  • スタイルエンジンはemotion固定

コメント

いやぁ〜、さすがでしたね、MUIの欠点をちゃんと克服しているというか、そんな印象でした。
CSS-in-JSベースのライブラリを検討していて、マテリアルデザインとは大きく異なるデザインを実装したい場合には、最有力候補なのではないでしょうか。

当初は、クリックイベントで発生する青いOutlineがあったのですが、それを消すのが若干面倒で、不評だったようです。
今大会では、しっかりそこも克服してきて扱いやすくなりましたね。

加えて、chakra-cliというものは、他のライブラリにはないの利点です。
このCLIがあることによって、デフォルトのテーマを変更したときのthemeの型の変更が非常に楽になります。
この点について、MUIは型の定義をdeclareで上書きするのが少し複雑で、差をつけてきた感じですね。

参考記事

https://zenn.dev/terrierscript/books/2021-05-chakra-ui

t_keshit_keshi

EntryNo.4608 Mantine

https://mantine.dev/

今大会のダークフォースぅぅぅ〜
知名度こそまだ高くないものの、「近年急上昇してきたライブラリ」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

Mantineのメリット

  • コンポーネントの豊富さは◎
  • ドキュメント充実
  • バージョンアップ、進化のスピードが速い
  • 便利なカスタムフックがあり、しかも種類が豊富
  • フォームのバリデーションも対応(Mantine Form)
  • ポリモーフィックコンポーネントを作ることのできるUtility関数が便利
  • デザインが落ち着いていて、業務系のアプリケーションを作るのに向きそう(主観)

Mantineのデメリット

  • 他のライブラリと比べてまだ知名度が低く、ネット上でにある情報も少ない

コメント

いやぁ〜、驚きでしたね。
正直、初めて聞いたライブラリだったんですけど、あまりの完成度にびっくりしました!

コンポーネントの豊富さについて、個人的には期間が選べるDate Pickerがあるのは、すごく助かります。
DatePickerChakraUIにはないですし、MUIだとMUIXという有料版になってしまいます。
このように他のライブラリに比べても、コンポーネントの守備範囲が広いのはMantineの大きな魅力です。

ポリモーフィックコンポーネントというのは、聞きなれない言葉ですが、以下のようなイメージです。

<Button /> // -> buttonタグになる
<Button component="a" /> // -> aタグになる

見た目はそのままに、HTMLタグを変更できます。
これを型安全に実現できるのがcreatePolymorphicComponentのすごいところで、初めて見たときは感動しましたね。

他のライブラリと比べて顕著な違いとしては、@mantine/hooksで豊富な種類のカスタムフックが提供されているところです。
ChakraUIもフックスを提供していますが、その数はMantineの方が多く、充実しています。

参考記事

https://zenn.dev/thr3a/articles/2c35b5d75081d7

t_keshit_keshi

EntryNo.1243 HeadlessUI

https://headlessui.com/

ヘッドレスという新たなアプローチぃぃぃ〜
彼らはゆぅぅぅ〜う、「UIライブラリに見た目は必要ない」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

HeadlessUIのメリット

  • スタイルを上書きする必要がなく、1からデザインを作っていくことができる
  • カスタマイズのしやすさは◎
  • Tailwind Labsが開発を進めており、tailwindCSSとの相性が◎
  • 近年のパフォーマンス的な観点で問題があると指摘され始めているCSS-in-JSを使わない選択が可能。

HeadlessUIのデメリット

  • カスタマイズするのが前提なので、初速は出ないかもしれない
  • コンポーネントがあまり豊富ではない

コメント

いやぁ〜、『ヘッドレス』、これが斬新な発想でしたね。
でも改めて言われてみると、むしろ挙動部分と見た目部分を一緒にしてしまう方が間違いで、ヘッドレスの発想こそが、UIライブラリの向かうべき本来の方向性という感じがします。

そもそもヘッドレスとは何か

例えばダイアログを例にとると、

挙動部分

  • ボタンを押すと、ダイアログが開く
  • ダイアログの背景(Backdrop)をクリックすると、ダイアログが閉じる
  • ダイアログが開いている間は、ダイアログの後ろにある要素はスクロールできない

見た目部分

  • Backdropの背景色はrgba(0,0,0,0.7)

というように、分類できそうです。
このとき、挙動部分がありがちな要件は固まっているのに対し、見た目部分は様々なデザインのバリエーションが考えられます。
見た目部分は「カスタマイズの要件が高い部分」だと言えそうです。
UIライブラリが挙動と見た目の両方に関心を持ってしまっている場合には、見た目を変更する際に①デフォルトでどういうCSSが当たっているのか調べる、②デフォルトであっているCSSを上書きする、という面倒なことになるかもしれません。
ヘッドレスは、この問題を解決します。

HeadlessUIは挙動とアクセシビリティを担保し、スタイルを持たないので、見た目は自由にこちらで変えられます。変幻自在のライブラリと呼ぶこともできそうです。

デザイナーさんが一番喜ぶライブラリかもしれません。

ただ、強調しておきたいのは、「ヘッドレスはHeadlessUIの専売特許ではない」という点です。
次にあげるRadix UIもヘッドレスです。
また、@mui/materialを使わないで、@mui/baseだけを使った場合、これもかなりヘッドレスに近いアプローチになります。

このようなことを考えると、HeadlessUIを導入する決め手は、意外とヘッドレスなUIを求めるか否かではなく、tailwindCSSを選ぶか否かということになるのかもしれません。

参考記事

https://www.codegrid.net/articles/2021-headless-ui-1/

t_keshit_keshi

EntryNo.2639 Radix UI

https://www.radix-ui.com/

アクセシビリティの高いコンポーネントを自在にぃぃぃ〜
彼らはゆぅぅぅ〜う、「UIコンポーネントの車輪の再発明に、いつまで時間を浪費しているの?」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

RadixUIのメリット

  • HeadlessUIよりもコンポーネントの種類が豊富
  • スタイルを上書きする必要がなく、1からデザインを作っていくことができる
  • アクセシビリティ対応が◎
  • カスタマイズのしやすさは◎
  • stitchesでもtailwindCSSでも何でもOKな姿勢が素晴らしい

Radix UIのデメリット

  • カスタマイズするのが前提なので、初速は出ないかもしれない
  • 昨年7月にメジャーリリース、ネット上にある情報はまだまだ少ない

コメント

どういうときになぜasChildをつける必要があるか、というようなところはReactに詳しい人でないと、理解が難しいのではないかと思います。

フルスクラッチでUIコンポーネントを開発することが面倒であれば、RadixUItailwindCSSをベースとしたshadcn/uiを一部で利用するなど、柔軟な技術選定も可能かもしれません。

個人的には注目しており、今後が期待できるライブラリです。

参考記事

https://zenn.dev/ynakamura/articles/d30ee1cb6f3a15

t_keshit_keshi

EntryNo.4192 Semantic UI React

https://react.semantic-ui.com/

美しい見た目のWebサイトをスピーディにぃぃぃ〜
彼らはゆぅぅぅ〜う、「冗長なBEMSMACSSとはおさらばだ」
さぁ、その実力をぉぉぉ〜、見ぃせつけろぉぉぉぉぉ〜!!!

レッツゲガンガンガン!!!

SemanticUIReactのメリット

  • コンポーネントの豊富さは○
  • sasslessに馴染みが深い人には扱いやすい

SemanticUIReactのデメリット

  • themingの仕組みがない
  • アクセシビリティ対応が不十分
  • ライブラリがアクティブにメンテナンスされておらず、ここ数年のコントリビュートは数得るほどしかない
  • will-changeという禁断のCSSが使用されているなど、メンテナンスしにくい面がある
  • 型安全性が低く、想定されていないpropsanyで受けつけてしまう

コメント

今から新規開発を始めるなら、SemanticUIReactを選ぶ選択はまずないと思います。
やめておいた方が無難です。

万一、SemanticUIReactを使う場合には、スタイルの変更は公式の方法に則って行うのが良さそうです。
Recreating GitHubというところにあるように、リポジトリをフォークして直接lessを上書きしていくような方向性です。

SemantciUIReactのスタイルの変更をCSS-in-JSで行うアプローチはオススメしません。
詳細度の問題に絶えず頭を悩まされることになりますし、バグの温床にもなりえます。
このアプローチでは、上書きしたいスタイルがsemantic-uiのデフォルトのスタイルよりも詳細度が高いのかどうか逐一確認しながら進めていくことになります。
非常に手間です。

!importantの辛み

ライブラリ側ですでに!importantが使われている箇所が多々あり、頑張って詳細度を考えても結局、!importantを使わざるを得ないという切ない感じになります。
具体的には次のようなコードです。

const button = css`
 &&&.ui.button:disabled {
  opacity: 0.9 !important;
}
`

Semantic UIなのに!importantという禁じ手を書かざるを得ないのは、あれ、セマンティクスってなんだっけ...?という気分にさせられます。

もちろん2016頃には有力なライブラリだったと思いますし、ライブラリのコントリビューターの方々には感謝したいです。
しかし、メンテナンスがアクティブに行われることは、もうないでしょう。
実際、下記参考記事のディスカッションは、Jack Lukicさんの次のような悲痛なコメントで締められています。

寄付金や広告の額は、開発者の給料の10分の1程度です。それは、貯金を取り崩すことなく、フルタイムで開発することを可能にする金額ではありません。

🥲

参考記事

https://github.com/Semantic-Org/Semantic-UI/issues/6109

t_keshit_keshi

EntryNo.0000 UIライブラリを使わない選択

長くなってしましたが、最後に
「UIライブラリを使わない」というのも非常に有力な手段です。

その理由は、UIライブラリは栄枯必衰で、移り変わりの激しいものだからです。
かつては有力な選択肢だったライブラリも時代の変遷を経て負債化してしまうかもしれません。

そうなるくらいなら、最初からライブラリに頼らないで実装する。
そういう考え方もありそうです。

ですが、まったくライブラリを使わないで、全部1から作るというのもかなり大変です。
Buttonコンポーネントくらいなら簡単に作れますが、ModalSelectといったコンポーネントになってくると、アクセシビリティを妥協せずに、挙動もミスなく作りきるのは、かなりの労力を必要とします。
この選択肢を取るならば、要所要所はreact-modalreact-selectなどを使うのが妥当な折衷案ということになりそうです。

UIライブラリに依存しないために

とはいえ、とにかく速いサービスのローンチが求められるスタートアップでは、悠長にコンポーネント群を整備している時間などありません。
そして、初速の開発スピードを優先したければ、やはりUIライブラリを使う方が得策です。

もしUIライブラリを使う決断をした場合には、UIライブラリは栄枯必衰という事実にきちんと向き合うべきです。
今はベストな選択も、5年後もそうであるとは言い切れません。

UIライブラリが技術的負債とならないようにするためには、できるだけライブラリに依存しないようにする工夫(=乗り換えやすくしておく工夫)が必要です。

その方法としては、例えば、

pages/hogePage.tsx
import { Button } from "@mui/material"

const HogePage = () => {
    return <Button />
}

のように、直接、ライブラリからimportするのではなくて、

components/Button.tsx
import { Button as MuiButton } from "@mui/material"

export const Button = styled(MuiButton)``
pages/hogePage.tsx
import { Button } from "./components/ui/Button"

const HogePage = () => {
    return <Button />
}

というように、敢えて一手間かませる、というやり方がありそうです。
そうすることによって、いつでもスタイルを変更することができ、ライブラリの使用をやめたり場合にも、

components/Button.tsx
import { styled } from "@emotion/react"

export const Button = styled.button`
 display: inline-flex;
 padding: 4px 8px;
 border-radius: 4px;
...
`

として、uiディレクトリ内の変更だけで済むので、移行しやすくなります。
多少面倒ではありますが、この一手間は将来的なリターンが大きく、有力なのではないかと思います。

ちなみに、ここ最近は実務で脱SemanticUIを目指しているのですが、この方向性でSemanticUIをラッピングしてから、段階的な移行を目指す手段をとっています。

t_keshit_keshi

まとめ

以上です!
使用経験のあるライブラリとそうでないライブラリの両方について書いたため、だいぶ主観的になってしまいました。その辺りは、コメントなどで、補っていただけますと幸いです🙏 (そういえばAntDesignについて忘れていたので、どなたかぜひ)