🎨

【Rails7】Rails7+Tailwind CSSにモーダルを追加する【Tailwind Stimulus Components】

2023/05/29に公開

前提

  • Rails7
  • Tailwind CSS
  • Hotwire

背景

Rails7ではオプションとしてアプリケーション作成時にCSSフレームワークを選択することができる(Tailwind CSS、Bootstrapなど)のですが、Bootstrapでは簡単に実装できるモーダルが、Tailwind CSSだとどうやって実現すればいいのか情報がまったくない状態でした。(単に私のサーチ能力がなさすぎるだけなのかもしれない)
Tailwind Stimulus Componentsというモジュールを使用することでモーダル機能をなんとか実現できたので、参考になれば幸いです。なお、TailwindCSS Stimulus Componentsにはモーダル以外にもドロップダウンメニューやトグルもあるみたいなので、ぜひチェックしてみてください。
https://www.npmjs.com/package/tailwindcss-stimulus-components?activeTab=readme

完成形


ボタン押下と背景押下でモーダルを閉じることができます

手順

importmapを使用してTailwind Stimulus Componentsを導入する

ターミナル
$ ./bin/importmap pin tailwindcss-stimulus-components

コマンドを叩くとconfig/importmap.rbに自動的に追記されます。

config/importmap.rb
# frozen_string_literal: true

# Pin npm packages by running ./bin/importmap

pin 'application', preload: true
pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true
pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js', preload: true
pin_all_from 'app/javascript/controllers', under: 'controllers'
pin "email-validator" # @2.0.4
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js"

Stimulusを既に導入してる場合、最下行の"@hotwired/stimulus"は3行目と重複するので削除します。

config/importmap.rb
# frozen_string_literal: true

# Pin npm packages by running ./bin/importmap

pin 'application', preload: true
pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true
pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js', preload: true
pin_all_from 'app/javascript/controllers', under: 'controllers'
pin "email-validator" # @2.0.4
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js"

app/javascript/controllers/modal_controller.jsを以下のように作成します。

app/javascript/controllers/modal_controller.js
import { Modal } from "tailwindcss-stimulus-components"


export default class ExtendedModal extends Modal {
  static targets = ["form"]

  connect() {
    super.connect()
  }
}

app/javascript/controllers/index.jsに追記してmodal_controller.jsを読み込む。

app/javascript/controllers/index.js
// Import and register all your controllers from the importmap under controllers/*

import { application } from "controllers/application"

(省略)

import { Modal } from "tailwindcss-stimulus-components"
application.register('modal', Modal)

modalパーシャルを作成する

浮かび上がってくるモーダルを作成します。
data-modal-target="container"でモーダルとしたい部分を囲います。
data-action="click->modal#closeBackground"は背景を押下することでモーダルを閉じられるようにするものです。

_modal.html.erb
<!-- Modal Container -->
<div data-modal-target="container" data-action="click->modal#closeBackground keyup@window->modal#closeWithKeyboard" class="hidden animated fadeIn fixed inset-0 overflow-y-auto flex items-center justify-center absolute" style="z-index: 9999;">
  <!-- Modal Inner Container -->
  <div class="max-h-screen w-full max-w-lg relative">
    <!-- Modal Card -->
    <div class="my-1 bg-white rounded shadow w-80 mx-auto">
      <div class="p-8">
        <h2 class="text-xl mb-4">モーダル</h2>
        
        <p class="mb-4">モーダル内テキスト</p>

        <div class="flex items-center flex-wrap mt-6 w-80 mx-auto">
          <button class="ml-5" data-action="click->modal#close">閉じるボタン</button>

          <%= button_to '処理を行うボタン', method_path, method: :post, class: "ml-5" %>
        </div>
      </div>
    </div>
  </div>
</div>

適用したい箇所をdata-controller="modal"の要素で囲み、render 'modal'でmodalパーシャルを読み込む

data-controller属性を付与すると、Stimulusがそれを検知し、対応する名前で登録されたcontrollerを使用します。modal-controllerを使用するためにdata-controller="modal"としたいのですが、今回はlink_toヘルパーを使用するためdata: { action: "click->modal#open" }と記述しています。

view.html.erb
<div data-controller="modal">
    <%= render 'modal' %>
    <%= link_to hoges_path, data: { action: "click->modal#open" } do %>
      <div>
        モーダルを開く
      </div>
    <% end %>
  </div>

CSSでスタイルを編集する(必要なら)

私の環境の場合はそのまま適用するとスタイルが崩れてしまっていたので以下のように修正しました。

application.css
#modal-background{
  position: absolute;
}

オプション

その他にも以下のような設定が可能なので、詳しくは以下のドキュメントを読んでください。

  • ユーザーが背景をクリックしたときにモーダルを閉じないようにする(Default: true)
  • モーダルの暗い透明な背景を追加することを無効にする
  • モーダルを開く要素(例:リンクが開かない)をクリックしたときにデフォルトのアクションが実行されないようにする(Default: true)
  • スクロール位置の復元を無効にする
  • モーダルの背景の色と透明度をrgba値で指定する(Default: rgba(0, 0, 0, 0.8))

https://www.npmjs.com/package/tailwindcss-stimulus-components?activeTab=readme

参考

https://www.colby.so/posts/handling-modal-forms-with-rails-and-hotwire
https://zenn.dev/hassan/articles/6c99abacfdcb8e
https://www.npmjs.com/package/tailwindcss-stimulus-components?activeTab=readme

Discussion