- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
11 KiB
Story 10.2: Fix Mobile Menu Issues
Status: review
Story
As a mobile user, I want a working menu that is easy to access and use on mobile devices, so that I can navigate the app and access all features.
Acceptance Criteria
- Given a user is using the app on a mobile device,
- When the user needs to access the menu or navigation,
- Then the system should:
- Display a functional mobile menu (hamburger menu or similar)
- Allow easy opening/closing of the menu
- Show all navigation options clearly
- Work with touch interactions smoothly
- Not interfere with content scrolling
Tasks / Subtasks
- Investigate current mobile menu implementation
- Check if mobile menu exists
- Identify menu component
- Document current issues
- Test on real mobile devices
- Implement or fix mobile menu
- Create responsive navigation component
- Add hamburger menu for mobile (< 768px)
- Implement menu open/close states
- Add backdrop/overlay when menu open
- Ensure close on backdrop click
- Optimize menu for touch
- Large touch targets (min 44x44px)
- Clear visual feedback on touch
- Smooth animations
- Accessible with screen readers
- Test menu on various mobile devices
- iOS Safari (iPhone)
- Chrome (Android)
- Different screen sizes
- Portrait and landscape orientations
Dev Notes
Bug Description
Problem: The menu has issues on mobile - may not open, close properly, or be accessible.
User Report: "Il paraît également qu'il y a un problème avec le menu en mode mobile" (There also seems to be a problem with the menu in mobile mode)
Expected Behavior:
- Hamburger menu visible on mobile
- Tapping menu icon opens full-screen or slide-out menu
- Menu items are large and easy to tap
- Tapping outside menu or X button closes menu
- Smooth animations and transitions
Current Behavior:
- Menu may not work on mobile
- Menu items may be too small to tap
- Menu may not close properly
- Poor UX overall
Technical Requirements
Responsive Breakpoints:
/* Tailwind defaults or custom */
sm: 640px
md: 768px
lg: 1024px
xl: 1280px
2xl: 1536px
Mobile Menu Pattern Options:
Option 1: Slide-out Menu (Recommended)
// keep-notes/components/MobileMenu.tsx
'use client'
import { useState } from 'react'
import { X } from 'lucide-react'
export function MobileMenu() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
{/* Hamburger button */}
<button
onClick={() => setIsOpen(true)}
className="lg:hidden p-4"
aria-label="Open menu"
>
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M3 12h18M3 6h18M3 18h18" stroke="currentColor" strokeWidth="2"/>
</svg>
</button>
{/* Backdrop */}
{isOpen && (
<div
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
onClick={() => setIsOpen(false)}
/>
)}
{/* Slide-out menu */}
<div className={`
fixed top-0 right-0 h-full w-80 bg-white z-50
transform transition-transform duration-300 ease-in-out
${isOpen ? 'translate-x-0' : 'translate-x-full'}
lg:hidden
`}>
{/* Header */}
<div className="flex justify-between items-center p-4 border-b">
<h2 className="text-lg font-semibold">Menu</h2>
<button
onClick={() => setIsOpen(false)}
className="p-2"
aria-label="Close menu"
>
<X size={24} />
</button>
</div>
{/* Menu items */}
<nav className="p-4 space-y-2">
<MenuButton to="/">All Notes</MenuButton>
<MenuButton to="/notebooks">Notebooks</MenuButton>
<MenuButton to="/labels">Labels</MenuButton>
<MenuButton to="/settings">Settings</MenuButton>
</nav>
</div>
</>
)
}
function MenuButton({ to, children }: { to: string; children: React.ReactNode }) {
return (
<a
href={to}
className="block px-4 py-3 rounded-lg hover:bg-gray-100 active:bg-gray-200"
style={{ minHeight: '44px' }} // Touch target size
>
{children}
</a>
)
}
Option 2: Full-Screen Menu
// Full-screen overlay menu
<div className={`
fixed inset-0 bg-white z-50
transform transition-transform duration-300
${isOpen ? 'translate-y-0' : '-translate-y-full'}
`}>
{/* Menu content */}
</div>
Option 3: Bottom Sheet (Material Design style)
// Bottom sheet menu
<div className={`
fixed bottom-0 left-0 right-0 bg-white rounded-t-3xl z-50
transform transition-transform duration-300
${isOpen ? 'translate-y-0' : 'translate-y-full'}
`}>
{/* Menu content */}
</div>
Implementation Checklist
Essential Features:
- Hamburger icon visible on mobile (< 768px)
- Menu opens with smooth animation
- Backdrop overlay when menu open
- Close on backdrop tap
- Close button (X) in menu header
- Menu items are full-width with min-height 44px
- Active state on menu items (hover/active)
- Keyboard accessible (Esc to close)
- Screen reader announcements
- Menu closes on navigation
Nice-to-Have Features:
- Swipe to close gesture
- Haptic feedback on open/close
- User profile in menu
- Search in menu
- Recent items in menu
Files to Create
// keep-notes/components/MobileMenu.tsx
'use client'
import { useState, useEffect } from 'react'
import { X, Home, Notebook, Tags, Settings } from 'lucide-react'
export function MobileMenu() {
const [isOpen, setIsOpen] = useState(false)
// Close menu on route change
useEffect(() => {
setIsOpen(false)
}, [pathname])
// Prevent body scroll when menu open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = ''
}
return () => {
document.body.style.overflow = ''
}
}, [isOpen])
return (
<>
<MenuButton onOpen={() => setIsOpen(true)} />
<MenuOverlay isOpen={isOpen} onClose={() => setIsOpen(false)} />
<MenuPanel isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
)
}
// ... rest of implementation
Files to Modify
Current Navigation/Header:
keep-notes/components/Header.tsx(likely exists)keep-notes/components/Navigation.tsx(if exists)keep-notes/app/layout.tsx- May need mobile menu wrapper
Testing Requirements
Test on Real Devices:
- iPhone SE (small screen)
- iPhone 14 Pro (large screen)
- Android phone (various sizes)
- iPad (tablet)
- Portrait and landscape
Test Scenarios:
- Tap hamburger → menu opens smoothly
- Tap backdrop → menu closes
- Tap X button → menu closes
- Tap menu item → navigates and closes menu
- Swipe gesture → menu closes (if implemented)
- Press Esc → menu closes
- Scroll content → menu stays open
Accessibility Testing:
- Screen reader announces menu state
- Keyboard navigation works
- Focus trap when menu open
- ARIA labels correct
Mobile UX Best Practices
Touch Targets:
- Minimum 44x44px (iOS)
- Minimum 48x48px (Android)
- Full-width buttons for easy tapping
Visual Design:
- Clear visual hierarchy
- Good contrast ratios
- Large, readable text (min 16px)
- Spacious padding
Animations:
- Smooth transitions (300ms or less)
- No janky animations
- Respect
prefers-reduced-motion
Performance:
- Menu renders quickly
- No layout shifts
- Smooth 60fps animations
References
- Responsive Navigation Patterns: https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/
- Mobile Navigation Best Practices: https://www.nngroup.com/articles/mobile-navigation/
- Touch Target Sizes: iOS HIG + Material Design guidelines
- Project Context:
_bmad-output/planning-artifacts/project-context.md - Current Navigation: Check
keep-notes/components/for nav components
Dev Agent Record
Implementation Plan
Current State Analysis (2026-01-17):
- Found existing mobile menu implementation in
keep-notes/components/header.tsx - Uses Radix UI Sheet component (lines 255-312)
- Hamburger button visible on mobile (
lg:hidden) - Navigation items: Notes, Reminders, Labels, Archive, Trash
- Touch targets:
px-4 py-3(approximately 44x44px minimum)
User Feedback (2026-01-17 - Galaxy S22 Ultra testing): ❌ CRITICAL: Interface overflows device screen (horizontal/vertical overflow) ❌ CRITICAL: Notes display must be different on mobile ❌ CRITICAL: Entire app behavior needs to be different on mobile mode ❌ CRITICAL: Many UI elements need mobile-specific adaptations ✅ Desktop interface must remain unchanged
Identified Issues:
- ❌ Interface overflow on mobile devices (Galaxy S22 Ultra)
- ❌ No body scroll prevention when menu opens (can scroll page behind menu)
- ❌ No explicit X close button in menu header
- ❌ No keyboard accessibility (Esc key to close)
- ❌ No focus management when menu opens
- ❌ Screen reader announcements incomplete
- ❌ Touch targets may be slightly below 44px on some devices
- ❌ No active state visual feedback on touch
- ❌ Note cards display same on mobile as desktop (not optimized)
- ❌ Overall UI not designed for mobile UX patterns
Fix Plan: Phase 1 - Mobile Menu Fixes (COMPLETED):
- ✅ Added
useEffectto prevent body scroll when menu is open - ✅ Added explicit X close button in SheetHeader
- ✅ Added keyboard event listener for Esc key
- ✅ Improved accessibility with ARIA attributes
- ✅ Ensured touch targets meet minimum 44x44px requirement
- ✅ Added visual feedback for active/touch states
Phase 2 - Full Mobile UX Overhaul (PENDING):
- Fix interface overflow issues
- Redesign note cards for mobile
- Implement mobile-specific layouts
- Test on real devices and browsers
- Create additional user stories for comprehensive mobile experience
Agent Model Used
claude-sonnet-4-5-20250929
Completion Notes List
- Created story file with comprehensive bug fix requirements
- Identified mobile menu patterns
- Recommended slide-out menu implementation
- Added mobile UX best practices
- Investigated current mobile menu implementation
- Documented identified issues and fix plan
- Implemented body scroll prevention
- Added X close button in menu header
- Implemented Esc key to close
- Enhanced accessibility with ARIA attributes
- Ensured touch targets meet 44x44px minimum
- Created Epic 12 for full mobile UX overhaul
- Verified no linter errors
File List
Files to Create:
keep-notes/components/MobileMenu.tsxkeep-notes/components/MenuButton.tsx(optional)keep-notes/components/MenuPanel.tsx(optional)
Files to Modify:
keep-notes/components/Header.tsx(or similar)keep-notes/app/layout.tsx