こんにちは。
今回はReact + Headless UI + Tailwind CSSでモーダルを作成してみたいと思います!
Headless UIとは、UIライブラリですがコンポーネントがデフォルトのスタイルを持っていないという特徴があります。
他のUIコンポーネントと比べ、自由にスタイルを設定することができ、スタイルがないので無駄なオーバーライドをする必要がなくなることがメリットとしてあります。
またユーティリティファーストであるTailwind CSSとの相性が良いとのことで、実際に使用してみたいと思います。
Tailwind CSSについて事前知識がない方は、こちらを一度ご覧ください。
それでは進めていきます!
目次
事前準備
事前にReact、Headless UI、Tailwind CSSそれぞれの環境を構築します。
React環境構築に関しては、こちらをご覧ください。
Tailwind CSSにの導入についてはこちらを参考に進めてください。
またHeadless UIを使用するため以下のパッケージをインストールします。
$ yarn add @headlessui/react
こちらにて事前の準備は完了です。
ディレクトリ構成
ディレクトリ構成は以下です。
root/
├── src/
├── components
├── Button/
├── index.js
├── Dialog/
├── index.js
├── App.js
├── index.css
├── index.js
実装
それでは実装に入っていきます!
Button
まずはボタンコンポーネントを作成します。
ボタンのスタイルはよしなに調整してください。
function Button(props) {
return (
<button
className='bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'
onClick={props.onClick}
>
{props.children}
</button>
)
}
export default Button
Dialog
次にDialogを作成します。
Headless UIにDialogが用意されているのでこちらをimportし、スタイルは公式サイトを参考に調整します。
注意点としてDialogのままだとコンポーネント名とかぶってしまうのでHuiDialog
とするようにしてます。
import { Dialog as HuiDialog } from '@headlessui/react'
import Button from '../Button'
function Dialog(props) {
return (
<HuiDialog
open={props.isOpen}
onClose={props.onClose}
className='fixed z-10 inset-0 overflow-y-auto'
>
<div className='flex items-center justify-center min-h-screen'>
<HuiDialog.Overlay className='fixed inset-0 bg-black opacity-30' />
<div className='relative bg-white rounded max-w-lg mx-auto p-5'>
<HuiDialog.Title
as='h3'
className='Description-lg font-medium leading-6 Description-gray-900'
>
{props.title}
</HuiDialog.Title>
<HuiDialog.Description className='mt-2 text-sm text-gray-500'>
{props.description}
</HuiDialog.Description>
<div className='mt-4'>
<Button onClick={props.onClose}>close</Button>
</div>
</div>
</div>
</HuiDialog>
)
}
export default Dialog
上記では必要最低限の実装にしていますが、Headless UIで用意されているTransition
を使用するとモーダルの開閉にアニメーションをつけることが可能みたいです。興味のある方は調べてみてください!
App.js
最後にDialogをApp.js
内で呼び出します。
今回はボタンクリック時にモーダルが開くようにしています。
import { useState } from 'react'
import Button from './components/Button'
import Dialog from './components/Dialog'
function App() {
const [isModalOpen, setIsModalOpen] = useState(false)
return (
<div className='mt-5 ml-5'>
<Button onClick={() => setIsModalOpen(true)}>Dialog Open</Button>
<Dialog
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title='Dialog Title'
description='Dialog Description. Dialog Description. Dialog Description. Dialog Description. Dialog Description.'
></Dialog>
</div>
);
}
export default App
完成
上記が完成のキャプチャとなります!
まとめ
Headless UIを使用すればすぐにモーダルなどの実装は可能ですが、スタイルは1からTailwind CSSで調整する必要があるので、Tailwind CSSの書き方に慣れていないとなかなか大変だと感じました。
もう少し試しながら書き方を覚えていきたいと思います。
最後までお読みいただきありがとうございます。