PlayGroundAdventCalender2024の15日目
こんにちは、デザインコースのHaruです
PlayGroundではデザインコースですが、個人ではWeb開発を全般的に学んでいます
そして今回はReactで使えるヘッドレスUIライブラおリについて紹介したいと思います
ヘッドレス UI ライブラリ とは
そもそもこれが何か知っていますか?
「スタイル以外の振る舞いを提供するライブラリ」
のことです
従来のUIライブラリでは元々スタイルがついています
ボタンには色がついてて、余白があって、ホバーしたりクリックした時に変化するというような感じです
それらがないのがヘッドレスUIライブラリとなります
そのため完全オリジナルのデザインにすることができるのです
いくつか紹介
- Radix UI
- shadcn/uiでも使われているライブラリ
- HeadlessUI
- TailwindCSSと同じ開発元なのでTailwindCSSとの相性がいい
- React aria
- Adobeが作っており、アクセシビリティに特化している
他にも色々あったり従来のUIライブラリがヘッドレス化していたりもするので、気になった方は調べてみてください!
実際に使ってコンポーネントを作ってみる
紹介した中でもTailwindCSSと相性といいHeadlessUIを使って、ドロップダウンメニューを作っていこうと思います

使用する技術構成
- React v18.3.1
- Vite v6.0.1
- Tailwind CSS v3.4.16
- @headlessui/react v2.2.0
環境構築
このTailwind CSSのドキュメントの手順でやっていきます
(本題とは違うので簡潔に進めます)
まずはViteでReactのプロジェクト作成
npm create vite@latest my-project -- --template react
Tailwind CSSをインストール
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Tailwind CSSの適用範囲を指定
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
他の不要なCSSは削除し、これだけ加える
@tailwind base;
@tailwind components;
@tailwind utilities;
これでTailwind CSSのセットアップまでできたので、実行する
npm run dev
HeadlessUIの導入
ではやっと本題のHeadlessUIを入れていきましょう
とは言っても、シンプルにインストールするだけです
npm install @headlessui/react
ドロップダウンメニューを作る
ここから作っていくのですが、ヘッドレスUIライブラリということがわかりやすいようにまずは何もスタイルを指定せず作ります
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
function App() {
return (
<Menu>
<MenuButton>open</MenuButton>
<MenuItems>
<MenuItem>
<a href="#">item1</a>
</MenuItem>
<MenuItem>
<a href="#">item2</a>
</MenuItem>
<MenuItem>
<a href="#">item3</a>
</MenuItem>
</MenuItems>
</Menu>
);
}
export default App;
これは本当に必要なものをimportしただけですね
では画面はどうなってるでしょうか?

MenuButton
のopenだけだ表示されています
まあ、これはドロップダウンメニューなので、クリックしてみます

中のMenuItems
が出てきました
これがドロップダウンなのかーってくらいスタイルないですよね笑
ただクリックしたら中身が出てくる挙動はこれだけで作れました
あとは好きにスタイリングすれば良いだけです
自作するより圧倒的に楽ですよね
そして、普通に使っている分にはスタイルがないだけに見えますが、ヘッドレスUIライブラリにはアクセシビリティが考慮されてるものが多いです
(スクリーンリーダーやキーボード操作など)
これもメリットの1つになります
でもまあ流石にこのままでは使わないのでスタイリングしていきましょう!
Tailwind CSS でスタイリング
一応HeadlessUIのドキュメントにはすでにスタイリングされたコード例も載っているので参考にしてみてください
アイコンは同じくTailwind CSSの開発者が作ったHeroiconsというものを使います

※Tailwind CSSの具体的な記法については解説しません
よくあるユーザーアイコンクリックしたら出てくるメニューにしてみようと思います
なのでまずはMenuButton
をアイコンにします
<MenuButton className={"rounded-full w-12 h-12 border"}>
<img
src="/image.png"
alt="user icon"
className="rounded-full"
/>
</MenuButton>

そしてMenuItems
にはありそうな感じのプロフィール・設定・ログアウトの3つを含めてみました
それぞれアイコンもつけています
<MenuItems
anchor={"bottom end"}
transition
className={"rounded-full w-12 h-12 border data-[hover]:brightness-95 data-[open]:brightness-95 data-[focus]:outline-1 data-[focus]:outline-neutral-700"}
>
<MenuItem>
<button className="group flex w-full items-center gap-2 rounded-lg py-2 px-3 data-[focus]:bg-neutral-400/10">
<UserIcon className="size-4 fill-black/50" />
プロフィール
</button>
</MenuItem>
<MenuItem>
<button className="group flex w-full items-center gap-2 rounded-lg py-2 px-3 data-[focus]:bg-neutral-400/10">
<Cog6ToothIcon className="size-4 fill-black/50" />
設定
</button>
</MenuItem>
<MenuItem>
<button className="group flex w-full items-center gap-2 rounded-lg py-2 px-3 data-[focus]:bg-neutral-400/10">
<ArrowRightStartOnRectangleIcon className="size-4 fill-black/50" />
ログアウト
</button>
</MenuItem>
</MenuItems>

このような感じになりました
transition
を使ってアニメーションをつけたり、ホバー時の変化をつけた完成系が以下になります!
まとめ
ヘッドレスUIライブラリの紹介と実際にドロップダウンメニューを作ってみました
MUIのようなUIライブラリと違い、置くだけで良いというのではないのでヘッドレスの方が良いわけではありません
自由度が高く独自のデザインにしたい時に便利なので、選択肢として知っておくのが良いのかと思います!
明日はyuukiさんです。よろしくお願いします!