-1024x576.png)
今回の例では、Tailwind CSS と Turbo + Stimulus を使い、以下の要素を持つナビゲーションバーを作りました
- ロゴ
- PC/モバイル対応のメニュー
- ログイン状況表示
- スーパーユーザー専用「新規登録」リンク
- ログアウト(確認ダイアログ付き)
- PCでもモバイルでも使えるプルダウンメニュー
この記事を書いてる人
082p
ご訪問、ありがとうございます!
システムエンジニア兼動画クリエーターとして活動しています。
主にRubyを得意とし、Ruby on Railsを中心にWebアプリケーション開発を行っています。
業務ではSQLやJavaScriptに触れることも多く、バックエンドからデータベースまで幅広く対応しています。
このブログでは、Ruby on RailsやPython(Django)などのWebアプリケーション開発やデータベース関連の技術記事を中心に、時々C#やWPFなどの開発内容についても発信しています。
ビュー構成 (app/views/shared/_navbar.html.erb)
<header class="bg-[#3E2723]">
<nav class="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8">
<!-- ロゴ -->
<div class="flex lg:flex-1 items-center gap-2">
<%= link_to root_path, class: "flex items-center gap-2" do %>
<%= image_tag "SKILL_LIFE.png", alt: "SKILL LIFE", class: "h-16 w-auto" %>
<% end %>
</div>
<!-- モバイル用バーガーメニュー -->
<div class="flex lg:hidden">
<button id="mobile-menu-button" class="text-[#FFF8E1] focus:outline-none">
<svg class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
</div>
<!-- PC用リンク -->
<div class="hidden lg:flex lg:flex-1 lg:justify-end gap-2 relative">
<% if user_signed_in? %>
<div class="relative">
<!-- プルダウンボタン -->
<button id="user-menu-button" class="flex items-center gap-2 text-[#FFF8E1] font-semibold px-4 py-2 rounded-md hover:bg-[#5D4037] transition-colors duration-200 focus:outline-none">
<% if current_user&.super_admin? %>
<span class="bg-yellow-500 text-white px-2 py-0.5 rounded-full text-xs">スーパーユーザー</span>
<% end %>
<%= current_user.login_id %>でログイン中
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<!-- プルダウンメニュー -->
<div id="user-menu" class="absolute right-0 mt-2 hidden w-48 bg-[#3E2723] rounded-md shadow-lg overflow-hidden ring-1 ring-black ring-opacity-20 z-50">
<% if current_user&.super_admin? %>
<%= link_to "新規登録 >", admin_new_user_path,
class: "px-4 py-2 text-[#FFF8E1] font-semibold rounded hover:bg-[#5D4037] transition-colors duration-150" %>
<div class="border-t border-[#5D4037]"></div>
<% end %>
<%= link_to "ログアウト >", destroy_user_session_path,
class: "px-4 py-2 text-[#FFF8E1] font-semibold rounded hover:bg-[#795548] transition-colors duration-150",
data: { turbo_method: :delete, turbo_confirm: "ログアウトしてよろしいですか?" } %>
</div>
</div>
<% else %>
<%= link_to "ログイン", new_user_session_path, class: "bg-[#795548] hover:bg-[#8D6E63] text-[#FFF8E1] px-3 py-2 rounded" %>
<% end %>
</div>
</nav>
<!-- モバイルメニュー -->
<div id="mobile-menu" class="hidden lg:hidden bg-[#3E2723] p-4">
<% if user_signed_in? %>
<span class="text-[#FFF8E1] font-semibold">
<% if current_user&.super_admin? %>
スーパーユーザー
<% end %>
<%= current_user.login_id %>でログイン中
</span>
<%= link_to "ログアウト >", destroy_user_session_path,
class: "block px-4 py-2 text-[#FFF8E1] font-semibold rounded hover:bg-[#8D6E63]",
data: { turbo_method: :delete, turbo_confirm: "ログアウトしてよろしいですか?" } %>
<% if current_user&.super_admin? %>
<%= link_to "新規登録 >", admin_new_user_path,
class: "block px-4 py-2 text-[#FFF8E1] font-semibold rounded hover:bg-[#5D4037]" %>
<% end %>
<% else %>
<%= link_to "ログイン", new_user_session_path, class: "block px-4 py-2 text-[#FFF8E1] font-semibold rounded hover:bg-[#8D6E63]" %>
<% end %>
</div>
<!-- スクリプト -->
<script>
document.addEventListener("turbo:load", () => {
const btn = document.getElementById("mobile-menu-button");
const menu = document.getElementById("mobile-menu");
const userBtn = document.getElementById("user-menu-button");
const userMenu = document.getElementById("user-menu");
// モバイルメニュー切り替え
if (btn && menu) {
if (!btn.dataset.bound) {
btn.addEventListener("click", () => menu.classList.toggle("hidden"));
btn.dataset.bound = "true";
}
}
// PCプルダウン切り替え
if (userBtn && userMenu) {
if (!userBtn.dataset.bound) {
userBtn.addEventListener("click", () => userMenu.classList.toggle("hidden"));
userBtn.dataset.bound = "true";
}
}
});
</script>
</header>
ポイント解説
1. ログイン状況の表示
- current_user.login_id を表示
- スーパーユーザーなら バッジ 付き (<span class="bg-yellow-500 text-white ...">)
2. プルダウンメニュー
- PCではユーザー名クリックで展開
- モバイルではバーガーメニュー内に表示
- Tailwindで影・角丸・ホバー効果を付与
3. ログアウト
- link_to に data: { turbo_method: :delete, turbo_confirm: "..." } を指定
- Turbo環境でも確認ダイアログが出て、DELETEリクエストでログアウト
4. イベント管理
- turbo:load イベントで DOM を初期化
- 多重バインド防止のため、dataset.bound フラグを使用
- モバイルとPCプルダウンを別々に管理
デザイン改善ポイント
- ring-1 ring-black ring-opacity-20 で プルダウンを浮かせる
- 区切り線で メニュー項目を視覚的に分離
- ホバー時の色を変えて ボタン感を出す
- PC・モバイルで同じデザイン言語を使用
まとめ
このナビゲーションバーは、Rails 8.1 + Tailwind + Turbo環境で、スーパーユーザー判定・ログイン状況・プルダウン・モバイル対応を統合しています。
ポイントは:
- Turbo 対応のイベント管理
- プルダウンのスタイル整備
- ユーザー権限による表示制御
- 確認ダイアログ付きログアウト
この実装をベースに、さらにアイコンやアニメーションを追加すると、より洗練されたUIになります。


