feat: Unify navigation with hamburger menu across all screen sizes

- Renamed MobileMenu to Menu component (no longer mobile-only)
- Added 500ms debounce to prevent accidental double-tap menu toggles
- Improved click-outside detection using ref-based containment check
- Removed mobile/desktop navigation split - menu now consistent everywhere
- All pages now use single hamburger menu on both mobile and desktop
- Simplified header layouts across index, sermon, profile, admin, and users pages

This provides a cleaner, more consistent UX with the hamburger menu available
on all screen sizes. The debounce prevents the menu from closing accidentally
when navigating between pages or double-tapping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-06 09:51:09 -05:00
parent 1cb0a4e9a2
commit cee37c78c4
6 changed files with 81 additions and 235 deletions

View File

@@ -2,90 +2,35 @@
<div class="min-h-screen bg-gray-50 flex flex-col">
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<!-- Mobile Layout -->
<div class="md:hidden">
<div class="flex items-center justify-between mb-3">
<NuxtLink to="/" class="hover:opacity-80">
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-16 w-auto" />
</NuxtLink>
<div class="flex items-center gap-2">
<QRCodeButton v-if="sermon" :sermon="sermon" />
<ClientOnly fallback-tag="div">
<MobileMenu
:is-authenticated="isAuthenticated"
:is-admin="isAdmin"
:show-home="true"
:current-path="route.fullPath"
/>
</ClientOnly>
</div>
</div>
<!-- Font Size Selector Below Buttons on Mobile -->
<div class="flex items-center justify-end gap-2">
<label for="font-size-mobile" class="text-xs font-medium text-gray-700 whitespace-nowrap">Size:</label>
<select
id="font-size-mobile"
v-model="fontSize"
class="px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-sm"
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</select>
</div>
</div>
<!-- Desktop Layout -->
<div class="hidden md:flex items-center justify-between">
<NuxtLink to="/" class="flex items-center space-x-4 hover:opacity-80">
<div class="flex items-center justify-between mb-3">
<NuxtLink to="/" class="hover:opacity-80">
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-16 w-auto" />
</NuxtLink>
<div class="flex items-end gap-4">
<NuxtLink
to="/"
class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 whitespace-nowrap"
>
🏠 Home
</NuxtLink>
<div class="flex flex-col gap-1">
<label for="font-size" class="text-xs font-medium text-gray-700">Font Size:</label>
<select
id="font-size"
v-model="fontSize"
class="px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-sm"
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</select>
</div>
<div class="flex items-center gap-2">
<QRCodeButton v-if="sermon" :sermon="sermon" />
<ClientOnly fallback-tag="div">
<template v-if="isAuthenticated">
<button
@click="handleLogout"
class="px-4 py-2 text-sm font-medium text-red-700 bg-red-50 rounded-md hover:bg-red-100 whitespace-nowrap"
>
Log Out
</button>
</template>
<template v-else>
<NuxtLink
:to="`/login?redirect=${encodeURIComponent(route.fullPath)}`"
class="px-4 py-2 text-sm font-medium text-green-700 bg-green-50 rounded-md hover:bg-green-100 whitespace-nowrap"
>
Log In
</NuxtLink>
<NuxtLink
to="/register"
class="px-4 py-2 text-sm font-medium text-blue-700 bg-blue-50 rounded-md hover:bg-blue-100 whitespace-nowrap"
>
Register
</NuxtLink>
</template>
<Menu
:is-authenticated="isAuthenticated"
:is-admin="isAdmin"
:show-home="true"
:current-path="route.fullPath"
/>
</ClientOnly>
</div>
</div>
<!-- Font Size Selector -->
<div class="flex items-center justify-end gap-2">
<label for="font-size" class="text-xs font-medium text-gray-700 whitespace-nowrap">Font Size:</label>
<select
id="font-size"
v-model="fontSize"
class="px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 text-sm"
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</select>
</div>
</div>
</header>