libra/docs/stories/story-1.4-base-ui-navigatio...

18 KiB

Story 1.4: Base UI & Navigation

Note: The color values in this story were implemented with the original Navy+Gold palette. These colors were updated in Epic 10 (Brand Color Refresh) to the new Charcoal+Warm Gray palette. See docs/brand.md for current color specifications.

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

  • Primary: Dark Navy Blue (#0A1F44) - backgrounds, headers
  • Accent: Gold (#D4AF37) - buttons, links, accents
  • Light Gold: #F4E4B8 - hover states
  • Off-White/Cream: #F9F7F4 - cards, content areas
  • Charcoal Gray: #2C3E50 - secondary text
  • Custom Tailwind colors configured via @theme

Navigation Bar

  • Fixed top position
  • Navy blue background
  • Logo placement: left on desktop, centered on mobile
  • Main menu items: Home, Booking, Posts, Login/Dashboard
  • Language toggle (Arabic/English) visible
  • Responsive mobile hamburger menu
  • Gold text for links, hover effects

Mobile Menu

  • Full-width dropdown or slide-in
  • Navy background with gold text
  • Touch-friendly targets (44px+ height)
  • Smooth open/close animation
  • Close on outside click or navigation
  • Navy blue background
  • Libra logo (smaller version)
  • Firm contact information
  • Links: Terms of Service, Privacy Policy
  • Copyright notice with current year
  • Sticky footer (always at bottom of viewport)

Layout Components

  • Card-based layouts with proper shadows and border-radius
  • Consistent spacing using Tailwind utilities
  • Container max-width: 1200px, centered
  • WCAG AA contrast compliance verified

Integration Requirements

  • Flux UI components used where available
  • Works with RTL and LTR layouts
  • Navigation state reflects current page
  • Login/logout state reflected in menu

Quality Requirements

  • Responsive on all breakpoints (mobile, tablet, desktop)
  • No horizontal scroll on any viewport
  • Fast loading (minimal CSS/JS)
  • Tests verify navigation rendering

Technical Notes

Tailwind Color Configuration

/* 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

<!-- 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

<!-- 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

<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

<!-- 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

<!-- 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

  • Navigation component renders on all pages
  • Logo displays correctly (or text fallback if SVG missing)
  • All menu links are visible and clickable
  • Active page is visually indicated in navigation
  • Navigation has correct navy background and gold text

Mobile Menu Tests

  • Hamburger menu icon visible on mobile viewports
  • Mobile menu toggles open on click
  • Mobile menu closes on outside click
  • Mobile menu closes when navigating to a link
  • Touch targets are at least 44px height

Authentication State Tests

  • Guest users see: Home, Booking, Posts, Login
  • Authenticated users see: Home, Booking, Posts, Dashboard, Logout
  • Logout form submits correctly and logs user out

Language Toggle Tests

  • Language toggle visible in navigation
  • Switching to Arabic applies RTL layout
  • Switching to English applies LTR layout
  • Language preference persists across page loads
  • Footer renders at bottom of viewport (sticky footer)
  • Footer contains logo (smaller version)
  • Footer contains Terms of Service and Privacy Policy links
  • Copyright year displays current year dynamically

Responsive Tests

  • No horizontal scroll on mobile (320px+)
  • No horizontal scroll on tablet (768px)
  • Layout adapts correctly at all breakpoints
  • Logo centered on mobile, left-aligned on desktop

Definition of Done

  • Navigation renders correctly on all viewports
  • Color scheme matches brand guidelines
  • Mobile menu opens/closes smoothly
  • Footer sticks to bottom of page
  • Language toggle functional
  • RTL/LTR layouts correct
  • All navigation links work
  • Login state reflected in menu
  • Tests pass for navigation
  • 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

  • Navigation responsive design implemented correctly
  • Mobile menu with proper touch targets (44px+)
  • RTL/LTR support via logical properties (border-s-2)
  • Auth-aware menu items (guest vs authenticated)
  • Language toggle functional with persistence
  • Footer sticky behavior working
  • All brand colors configured in Tailwind theme
  • 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

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.