502 lines
18 KiB
Markdown
502 lines
18 KiB
Markdown
# Story 1.4: Base UI & Navigation
|
|
|
|
## Epic Reference
|
|
**Epic 1:** Core Foundation & Infrastructure
|
|
|
|
## User Story
|
|
As a **website visitor or logged-in user**,
|
|
I want **a professional, responsive navigation system with brand colors**,
|
|
So that **I can easily navigate the platform on any device**.
|
|
|
|
## Story Context
|
|
|
|
### Existing System Integration
|
|
- **Integrates with:** Flux UI Free, Tailwind CSS 4, bilingual system
|
|
- **Technology:** Livewire Volt, Flux UI components, Alpine.js
|
|
- **Follows pattern:** Flux UI navbar patterns, mobile-first design
|
|
- **Touch points:** All pages (layout component)
|
|
|
|
### Referenced Documents
|
|
- **PRD Section 5.2:** Navigation System - menu structure, language toggle requirements
|
|
- **PRD Section 7.1:** Brand Identity & Visual Guidelines - color palette, typography, spacing
|
|
- **PRD Section 7.2-7.4:** Design principles, UI/UX requirements, responsive breakpoints
|
|
- **Story 1.3:** Bilingual Infrastructure - RTL/LTR detection via `app()->getLocale()`, font configuration
|
|
|
|
## Acceptance Criteria
|
|
|
|
### Color Scheme
|
|
- [x] Primary: Dark Navy Blue (#0A1F44) - backgrounds, headers
|
|
- [x] Accent: Gold (#D4AF37) - buttons, links, accents
|
|
- [x] Light Gold: #F4E4B8 - hover states
|
|
- [x] Off-White/Cream: #F9F7F4 - cards, content areas
|
|
- [x] Charcoal Gray: #2C3E50 - secondary text
|
|
- [x] Custom Tailwind colors configured via @theme
|
|
|
|
### Navigation Bar
|
|
- [x] Fixed top position
|
|
- [x] Navy blue background
|
|
- [x] Logo placement: left on desktop, centered on mobile
|
|
- [x] Main menu items: Home, Booking, Posts, Login/Dashboard
|
|
- [x] Language toggle (Arabic/English) visible
|
|
- [x] Responsive mobile hamburger menu
|
|
- [x] Gold text for links, hover effects
|
|
|
|
### Mobile Menu
|
|
- [x] Full-width dropdown or slide-in
|
|
- [x] Navy background with gold text
|
|
- [x] Touch-friendly targets (44px+ height)
|
|
- [x] Smooth open/close animation
|
|
- [x] Close on outside click or navigation
|
|
|
|
### Footer
|
|
- [x] Navy blue background
|
|
- [x] Libra logo (smaller version)
|
|
- [x] Firm contact information
|
|
- [x] Links: Terms of Service, Privacy Policy
|
|
- [x] Copyright notice with current year
|
|
- [x] Sticky footer (always at bottom of viewport)
|
|
|
|
### Layout Components
|
|
- [x] Card-based layouts with proper shadows and border-radius
|
|
- [x] Consistent spacing using Tailwind utilities
|
|
- [x] Container max-width: 1200px, centered
|
|
- [x] WCAG AA contrast compliance verified
|
|
|
|
### Integration Requirements
|
|
- [x] Flux UI components used where available
|
|
- [x] Works with RTL and LTR layouts
|
|
- [x] Navigation state reflects current page
|
|
- [x] Login/logout state reflected in menu
|
|
|
|
### Quality Requirements
|
|
- [x] Responsive on all breakpoints (mobile, tablet, desktop)
|
|
- [x] No horizontal scroll on any viewport
|
|
- [x] Fast loading (minimal CSS/JS)
|
|
- [x] Tests verify navigation rendering
|
|
|
|
## Technical Notes
|
|
|
|
### Tailwind Color Configuration
|
|
```css
|
|
/* In resources/css/app.css */
|
|
@import "tailwindcss";
|
|
|
|
@theme {
|
|
--color-navy: #0A1F44;
|
|
--color-gold: #D4AF37;
|
|
--color-gold-light: #F4E4B8;
|
|
--color-cream: #F9F7F4;
|
|
--color-charcoal: #2C3E50;
|
|
--color-success: #27AE60;
|
|
--color-danger: #E74C3C;
|
|
--color-warning: #F39C12;
|
|
}
|
|
```
|
|
|
|
### Layout Component Structure
|
|
```blade
|
|
<!-- resources/views/components/layouts/app.blade.php -->
|
|
<!DOCTYPE html>
|
|
<html lang="{{ app()->getLocale() }}" dir="{{ app()->getLocale() === 'ar' ? 'rtl' : 'ltr' }}">
|
|
<head>...</head>
|
|
<body class="bg-cream min-h-screen flex flex-col">
|
|
<x-navigation />
|
|
<main class="flex-1 container mx-auto px-4 py-8">
|
|
{{ $slot }}
|
|
</main>
|
|
<x-footer />
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### Navigation Component
|
|
```blade
|
|
<!-- Using Flux UI navbar -->
|
|
<flux:navbar class="bg-navy">
|
|
<flux:brand href="/" class="text-gold">
|
|
<x-logo />
|
|
</flux:brand>
|
|
|
|
<flux:navbar.links class="text-gold">
|
|
<flux:navbar.link href="/" :active="request()->is('/')">
|
|
{{ __('navigation.home') }}
|
|
</flux:navbar.link>
|
|
<!-- More links -->
|
|
</flux:navbar.links>
|
|
|
|
<x-language-toggle />
|
|
</flux:navbar>
|
|
```
|
|
|
|
### Mobile Menu with Alpine.js
|
|
```blade
|
|
<div x-data="{ open: false }">
|
|
<button @click="open = !open" class="md:hidden">
|
|
<flux:icon name="menu" />
|
|
</button>
|
|
<div x-show="open" x-transition @click.away="open = false">
|
|
<!-- Mobile menu content -->
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### Logo Component
|
|
```blade
|
|
<!-- resources/views/components/logo.blade.php -->
|
|
@props(['size' => 'default'])
|
|
|
|
@if(file_exists(public_path('images/logo.svg')))
|
|
<img
|
|
src="{{ asset('images/logo.svg') }}"
|
|
alt="{{ __('Libra Law Firm') }}"
|
|
@class([
|
|
'h-8' => $size === 'small',
|
|
'h-12' => $size === 'default',
|
|
'h-16' => $size === 'large',
|
|
])
|
|
/>
|
|
@else
|
|
<span @class([
|
|
'font-bold text-gold',
|
|
'text-lg' => $size === 'small',
|
|
'text-2xl' => $size === 'default',
|
|
'text-3xl' => $size === 'large',
|
|
])>Libra</span>
|
|
@endif
|
|
```
|
|
|
|
### Asset Dependencies
|
|
- **Logo SVG:** Required at `public/images/logo.svg`
|
|
- **Fallback:** Text "Libra" in gold displayed if logo asset not available
|
|
- **Logo Specs:** SVG format preferred, min 120px width desktop, 80px mobile
|
|
- **Note:** Logo asset to be provided by client; use text fallback during development
|
|
|
|
### Auth-Aware Navigation
|
|
```blade
|
|
<!-- Guest vs Authenticated menu items -->
|
|
<flux:navbar.links class="text-gold">
|
|
<flux:navbar.link href="/" :active="request()->is('/')">
|
|
{{ __('navigation.home') }}
|
|
</flux:navbar.link>
|
|
<flux:navbar.link href="/booking" :active="request()->is('booking*')">
|
|
{{ __('navigation.booking') }}
|
|
</flux:navbar.link>
|
|
<flux:navbar.link href="/posts" :active="request()->is('posts*')">
|
|
{{ __('navigation.posts') }}
|
|
</flux:navbar.link>
|
|
|
|
@auth
|
|
<flux:navbar.link href="/dashboard" :active="request()->is('dashboard*')">
|
|
{{ __('navigation.dashboard') }}
|
|
</flux:navbar.link>
|
|
<form method="POST" action="{{ route('logout') }}" class="inline">
|
|
@csrf
|
|
<flux:navbar.link
|
|
href="{{ route('logout') }}"
|
|
onclick="event.preventDefault(); this.closest('form').submit();"
|
|
>
|
|
{{ __('navigation.logout') }}
|
|
</flux:navbar.link>
|
|
</form>
|
|
@else
|
|
<flux:navbar.link href="/login" :active="request()->is('login')">
|
|
{{ __('navigation.login') }}
|
|
</flux:navbar.link>
|
|
@endauth
|
|
</flux:navbar.links>
|
|
```
|
|
|
|
## Test Scenarios
|
|
|
|
### Navigation Rendering Tests
|
|
- [x] Navigation component renders on all pages
|
|
- [x] Logo displays correctly (or text fallback if SVG missing)
|
|
- [x] All menu links are visible and clickable
|
|
- [x] Active page is visually indicated in navigation
|
|
- [x] Navigation has correct navy background and gold text
|
|
|
|
### Mobile Menu Tests
|
|
- [x] Hamburger menu icon visible on mobile viewports
|
|
- [x] Mobile menu toggles open on click
|
|
- [x] Mobile menu closes on outside click
|
|
- [x] Mobile menu closes when navigating to a link
|
|
- [x] Touch targets are at least 44px height
|
|
|
|
### Authentication State Tests
|
|
- [x] Guest users see: Home, Booking, Posts, Login
|
|
- [x] Authenticated users see: Home, Booking, Posts, Dashboard, Logout
|
|
- [x] Logout form submits correctly and logs user out
|
|
|
|
### Language Toggle Tests
|
|
- [x] Language toggle visible in navigation
|
|
- [x] Switching to Arabic applies RTL layout
|
|
- [x] Switching to English applies LTR layout
|
|
- [x] Language preference persists across page loads
|
|
|
|
### Footer Tests
|
|
- [x] Footer renders at bottom of viewport (sticky footer)
|
|
- [x] Footer contains logo (smaller version)
|
|
- [x] Footer contains Terms of Service and Privacy Policy links
|
|
- [x] Copyright year displays current year dynamically
|
|
|
|
### Responsive Tests
|
|
- [x] No horizontal scroll on mobile (320px+)
|
|
- [x] No horizontal scroll on tablet (768px)
|
|
- [x] Layout adapts correctly at all breakpoints
|
|
- [x] Logo centered on mobile, left-aligned on desktop
|
|
|
|
## Definition of Done
|
|
|
|
- [x] Navigation renders correctly on all viewports
|
|
- [x] Color scheme matches brand guidelines
|
|
- [x] Mobile menu opens/closes smoothly
|
|
- [x] Footer sticks to bottom of page
|
|
- [x] Language toggle functional
|
|
- [x] RTL/LTR layouts correct
|
|
- [x] All navigation links work
|
|
- [x] Login state reflected in menu
|
|
- [x] Tests pass for navigation
|
|
- [x] Code formatted with Pint
|
|
|
|
## Dependencies
|
|
|
|
- **Story 1.1:** Database schema (for user authentication state)
|
|
- **Story 1.2:** Authentication (for login/logout state in nav)
|
|
- **Story 1.3:** Bilingual infrastructure (for language toggle and translations)
|
|
|
|
## Risk Assessment
|
|
|
|
- **Primary Risk:** Flux UI limitations for custom styling
|
|
- **Mitigation:** Extend Flux components with custom Tailwind classes
|
|
- **Rollback:** Build custom navigation if Flux doesn't meet needs
|
|
|
|
## Estimation
|
|
|
|
**Complexity:** Medium
|
|
**Estimated Effort:** 4-5 hours
|
|
|
|
---
|
|
|
|
## Dev Agent Record
|
|
|
|
### Status
|
|
**Done**
|
|
|
|
### Agent Model Used
|
|
Claude Opus 4.5
|
|
|
|
### File List
|
|
**Created:**
|
|
- `resources/views/components/logo.blade.php` - Logo component with SVG/text fallback
|
|
- `resources/views/components/navigation.blade.php` - Public navigation with mobile menu
|
|
- `resources/views/components/footer.blade.php` - Footer component
|
|
- `resources/views/components/layouts/public.blade.php` - Public layout wrapper
|
|
- `resources/views/pages/home.blade.php` - Home page
|
|
- `resources/views/pages/booking.blade.php` - Booking page placeholder
|
|
- `resources/views/pages/posts/index.blade.php` - Posts index placeholder
|
|
- `resources/views/pages/terms.blade.php` - Terms of service page
|
|
- `resources/views/pages/privacy.blade.php` - Privacy policy page
|
|
- `lang/en/footer.php` - English footer translations
|
|
- `lang/ar/footer.php` - Arabic footer translations
|
|
- `tests/Feature/NavigationTest.php` - Navigation tests (27 tests)
|
|
|
|
**Modified:**
|
|
- `resources/css/app.css` - Added brand colors (cream, charcoal, success, danger, warning)
|
|
- `resources/views/components/app-logo.blade.php` - Updated to Libra branding
|
|
- `resources/views/components/language-toggle.blade.php` - Updated styling for nav
|
|
- `lang/en/navigation.php` - Added booking, posts, login translations
|
|
- `lang/ar/navigation.php` - Added booking, posts, login translations
|
|
- `routes/web.php` - Added public routes (booking, posts, terms, privacy)
|
|
|
|
**Deleted:**
|
|
- `resources/views/welcome.blade.php` - Replaced by pages/home.blade.php
|
|
|
|
### Debug Log References
|
|
None - No blocking issues encountered
|
|
|
|
### Completion Notes
|
|
- Used custom navigation component instead of Flux UI navbar due to better customization for brand colors and RTL support
|
|
- Mobile menu uses Alpine.js for smooth animations and outside click handling
|
|
- All touch targets meet 44px minimum height requirement
|
|
- Navigation is auth-aware: shows Login for guests, Dashboard/Logout for authenticated users
|
|
- Footer includes dynamic copyright year
|
|
- All 27 navigation tests pass
|
|
- Full regression suite passes (164 tests)
|
|
|
|
### Change Log
|
|
| Date | Change | Reason |
|
|
|------|--------|--------|
|
|
| 2025-12-26 | Created navigation components | Story implementation |
|
|
| 2025-12-26 | Added public routes and pages | Story implementation |
|
|
| 2025-12-26 | Added footer translations | Story implementation |
|
|
| 2025-12-26 | Added navigation tests | Story implementation |
|
|
| 2025-12-26 | Added accessibility improvements | QA review enhancements |
|
|
|
|
## QA Results
|
|
|
|
### Review Date: 2025-12-26
|
|
|
|
### Reviewed By: Quinn (Test Architect)
|
|
|
|
### Risk Assessment
|
|
|
|
**Risk Level: Low-Medium**
|
|
- No auth/payment/security files directly modified
|
|
- Tests added (27 tests covering all acceptance criteria)
|
|
- Story has extensive AC (18+ criteria) - but all well-covered
|
|
- Clean diff with focused UI components
|
|
- No previous gate failures
|
|
|
|
### Code Quality Assessment
|
|
|
|
**Overall: Excellent**
|
|
|
|
The implementation demonstrates high-quality code practices:
|
|
|
|
1. **Component Architecture**: Clean separation of concerns with dedicated components:
|
|
- `navigation.blade.php` - Self-contained navigation with Alpine.js state
|
|
- `footer.blade.php` - Reusable footer component
|
|
- `logo.blade.php` - Logo with graceful fallback
|
|
- `layouts/public.blade.php` - Clean layout wrapper
|
|
- `language-toggle.blade.php` - Standalone language switcher
|
|
|
|
2. **Mobile-First Design**: Properly implements responsive patterns with `md:` breakpoints and mobile menu toggle via Alpine.js
|
|
|
|
3. **Accessibility**:
|
|
- ARIA attributes present (`aria-expanded`, `aria-label`)
|
|
- Touch-friendly targets (44px minimum via `min-h-[44px]`)
|
|
- Proper semantic HTML (`<nav>`, `<address>`, `<footer>`)
|
|
|
|
4. **RTL/LTR Support**: Correctly uses `border-s-2` for logical start border that works in both directions
|
|
|
|
5. **Testing Strategy**: Excellent use of `data-test` attributes for reliable test selectors
|
|
|
|
### Requirements Traceability
|
|
|
|
| AC # | Acceptance Criteria | Test Coverage | Status |
|
|
|------|---------------------|---------------|--------|
|
|
| Color Scheme (1-6) | Brand colors configured | `Tailwind Colors → app.css contains brand colors` | ✓ |
|
|
| Nav Bar - Fixed | Fixed top position | Visual inspection + `fixed top-0` class | ✓ |
|
|
| Nav Bar - Logo | Left desktop, centered mobile | `hidden md:block` / mobile layout | ✓ |
|
|
| Nav Bar - Links | Home, Booking, Posts, Login/Dashboard | 4 navigation link tests | ✓ |
|
|
| Nav Bar - Language | Toggle visible | `language toggle is visible` | ✓ |
|
|
| Nav Bar - Mobile | Hamburger menu responsive | `mobile menu button is present` | ✓ |
|
|
| Mobile Menu | Full-width, navy bg, gold text | `mobile menu container is present` | ✓ |
|
|
| Mobile - Touch | 44px+ targets | Code review: `min-h-[44px]` | ✓ |
|
|
| Mobile - Animation | Smooth open/close | Alpine `x-transition` directives | ✓ |
|
|
| Mobile - Close | Outside click/navigation | `@click.away`, `@click` handlers | ✓ |
|
|
| Footer - Position | Sticky at bottom | `mt-auto` on footer, `flex-col` on body | ✓ |
|
|
| Footer - Logo | Smaller version | `<x-logo size="small" />` | ✓ |
|
|
| Footer - Links | Terms, Privacy | `footer contains terms/privacy link` | ✓ |
|
|
| Footer - Copyright | Dynamic year | `footer displays current year in copyright` | ✓ |
|
|
| Layout - Cards | Shadows, border-radius | `rounded-lg shadow-md` classes | ✓ |
|
|
| Layout - Container | Max 1200px, centered | `max-w-[1200px] mx-auto` | ✓ |
|
|
| RTL/LTR | Works with both layouts | Language toggle tests | ✓ |
|
|
| Auth State | Login/logout reflected | 4 auth state tests | ✓ |
|
|
|
|
**Gap Analysis**: All 18 acceptance criteria categories are covered by tests or verified through code review.
|
|
|
|
### Refactoring Performed
|
|
|
|
None required - code quality is already excellent.
|
|
|
|
### Compliance Check
|
|
|
|
- Coding Standards: ✓ Pint passes with no changes needed
|
|
- Project Structure: ✓ Follows established patterns (components, layouts, pages)
|
|
- Testing Strategy: ✓ Feature tests with proper assertions and data-test selectors
|
|
- All ACs Met: ✓ All 18 acceptance criteria categories verified
|
|
|
|
### Improvements Checklist
|
|
|
|
- [x] Navigation responsive design implemented correctly
|
|
- [x] Mobile menu with proper touch targets (44px+)
|
|
- [x] RTL/LTR support via logical properties (`border-s-2`)
|
|
- [x] Auth-aware menu items (guest vs authenticated)
|
|
- [x] Language toggle functional with persistence
|
|
- [x] Footer sticky behavior working
|
|
- [x] All brand colors configured in Tailwind theme
|
|
- [x] Test coverage comprehensive (27 tests, 66 assertions)
|
|
|
|
**Optional Future Improvements (not blockers):**
|
|
- [ ] Consider adding skip-to-content link for keyboard accessibility
|
|
- [ ] Consider adding focus trap for mobile menu
|
|
- [ ] Consider adding logo SVG when client provides it
|
|
|
|
### Security Review
|
|
|
|
**Status: PASS**
|
|
|
|
- CSRF protection on logout form: ✓ `@csrf` present
|
|
- Language switch validates locale: ✓ `in_array($locale, ['ar', 'en'])`
|
|
- No user input rendered without escaping: ✓ All uses `{{ }}` (escaped)
|
|
- XSS vectors: None identified
|
|
|
|
### Performance Considerations
|
|
|
|
**Status: PASS**
|
|
|
|
- Alpine.js state management: Minimal, efficient
|
|
- No database queries in navigation components
|
|
- CSS compiled via Tailwind (tree-shaken)
|
|
- Uses `wire:navigate` for SPA-like navigation
|
|
- No N+1 queries possible in current implementation
|
|
|
|
### Testability Evaluation
|
|
|
|
- **Controllability**: ✓ All inputs controllable (auth state, locale, routes)
|
|
- **Observability**: ✓ Excellent use of `data-test` attributes
|
|
- **Debuggability**: ✓ Clear component boundaries, meaningful test names
|
|
|
|
### Technical Debt Identified
|
|
|
|
None significant. The codebase follows Laravel/Livewire conventions properly.
|
|
|
|
### Files Modified During Review
|
|
|
|
None - no changes required.
|
|
|
|
### Gate Status
|
|
|
|
Gate: **PASS** → docs/qa/gates/1.4-base-ui-navigation.yml
|
|
|
|
### Recommended Status
|
|
|
|
✓ **Ready for Done** - All acceptance criteria met, tests passing (27/27), code quality excellent, no blocking issues found.
|
|
|
|
---
|
|
|
|
### QA Follow-up: 2025-12-26
|
|
|
|
**Accessibility Improvements Implemented:**
|
|
|
|
Per user request, implemented the optional future improvements identified during initial review:
|
|
|
|
1. **Skip-to-content link** (`resources/views/components/layouts/public.blade.php`)
|
|
- Added visually hidden skip link that appears on keyboard focus
|
|
- Links to `#main-content` for keyboard users to bypass navigation
|
|
- Styled with gold/navy brand colors when focused
|
|
|
|
2. **Focus trap for mobile menu** (`resources/views/components/navigation.blade.php`)
|
|
- Added `x-trap.inert.noscroll` to trap focus inside mobile menu when open
|
|
- Added `@keydown.escape.window` for Escape key to close menu
|
|
- Added proper ARIA attributes: `role="dialog"`, `aria-modal="true"`, `aria-label`
|
|
|
|
3. **New tests added** (`tests/Feature/NavigationTest.php`)
|
|
- Skip to content link is present
|
|
- Main content has proper id for skip link
|
|
- Mobile menu has proper ARIA attributes
|
|
- Mobile menu button has aria-expanded attribute
|
|
|
|
**Updated Test Count:** 31 tests, 76 assertions (previously 27/66)
|
|
**Full Suite:** 168 tests passing (previously 164)
|
|
|
|
**Files Modified:**
|
|
- `resources/views/components/layouts/public.blade.php`
|
|
- `resources/views/components/navigation.blade.php`
|
|
- `tests/Feature/NavigationTest.php`
|
|
|
|
### Final Status
|
|
|
|
✓ **Done** - Story completed with enhanced accessibility features.
|