reviewed epic 9 stories
This commit is contained in:
@@ -8,45 +8,67 @@ As a **visitor**,
|
||||
I want **to see the Libra scales logo prominently displayed**,
|
||||
So that **I recognize the firm's branding**.
|
||||
|
||||
## Dependencies
|
||||
- **Story 9.1:** Color System Implementation (for brand colors)
|
||||
- **Prerequisite:** Logo SVG/PNG assets must be provided or placeholder created
|
||||
- **Note:** Footer integration deferred to Story 9.7; Email templates to Epic 8
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Logo Placement
|
||||
- [ ] Navigation: Top left (desktop), centered (mobile)
|
||||
- [ ] Footer: Smaller version
|
||||
- [ ] Email templates: Header
|
||||
- [ ] PDF exports: Header
|
||||
- [ ] Footer: Smaller version (integrated when footer created in Story 9.7)
|
||||
- [ ] Email templates: Header (integrated when email templates created in Epic 8)
|
||||
- [ ] PDF exports: Header (integrated when PDF exports created)
|
||||
|
||||
### Logo Specifications
|
||||
- [ ] Minimum size: 120px (desktop), 80px (mobile)
|
||||
- [ ] Clear space: 20px padding minimum
|
||||
- [ ] Minimum size: 120px width (desktop), 80px width (mobile)
|
||||
- [ ] Clear space: 20px padding minimum around logo
|
||||
|
||||
### Format Support
|
||||
- [ ] SVG primary (scalable)
|
||||
- [ ] PNG fallback
|
||||
- [ ] SVG primary (scalable, preferred)
|
||||
- [ ] PNG fallback (for email clients that don't support SVG)
|
||||
|
||||
### Color Variations
|
||||
- [ ] Full color (gold on navy)
|
||||
- [ ] Reversed (navy on light)
|
||||
- [ ] Monochrome gold
|
||||
- [ ] **Full color:** Gold (#D4AF37) logo on Navy (#0A1F44) background
|
||||
- [ ] **Reversed:** Navy (#0A1F44) logo on light/cream (#F9F7F4) background
|
||||
- [ ] **Monochrome:** Single-color gold (#D4AF37) version
|
||||
|
||||
### Features
|
||||
- [ ] Responsive sizing
|
||||
- [ ] Accessible alt text
|
||||
- [ ] Responsive sizing based on viewport
|
||||
- [ ] Accessible alt text: "Libra Law Firm" (translatable)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Existing Component
|
||||
An `app-logo.blade.php` component already exists at `resources/views/components/app-logo.blade.php`. This story will **replace** it with a more robust implementation supporting variants and sizes.
|
||||
|
||||
**Files to modify:**
|
||||
- `resources/views/components/app-logo.blade.php` - Replace with new implementation
|
||||
- `resources/views/components/app-logo-icon.blade.php` - Update or remove
|
||||
- `resources/views/components/layouts/app/header.blade.php` - Update logo usage (lines 11, 96)
|
||||
|
||||
**Files to create:**
|
||||
- `public/images/logo.svg` - Full color logo
|
||||
- `public/images/logo-reversed.svg` - Reversed color logo
|
||||
- `public/images/logo-mono.svg` - Monochrome logo
|
||||
- `public/images/logo.png` - PNG fallback
|
||||
|
||||
### Logo Component Implementation
|
||||
|
||||
```blade
|
||||
<!-- resources/views/components/logo.blade.php -->
|
||||
<!-- resources/views/components/app-logo.blade.php -->
|
||||
@props([
|
||||
'size' => 'default',
|
||||
'variant' => 'full'
|
||||
'variant' => 'full',
|
||||
'showText' => true
|
||||
])
|
||||
|
||||
@php
|
||||
$sizes = [
|
||||
'small' => 'h-8',
|
||||
'default' => 'h-12',
|
||||
'large' => 'h-16',
|
||||
'small' => 'h-8 min-w-[80px]', // Mobile minimum
|
||||
'default' => 'h-12 min-w-[120px]', // Desktop default
|
||||
'large' => 'h-16 min-w-[160px]', // Large displays
|
||||
];
|
||||
|
||||
$variants = [
|
||||
@@ -54,23 +76,116 @@ $variants = [
|
||||
'reversed' => 'logo-reversed.svg',
|
||||
'mono' => 'logo-mono.svg',
|
||||
];
|
||||
|
||||
$sizeClass = $sizes[$size] ?? $sizes['default'];
|
||||
$logoFile = $variants[$variant] ?? $variants['full'];
|
||||
@endphp
|
||||
|
||||
<img
|
||||
src="{{ asset('images/' . $variants[$variant]) }}"
|
||||
alt="{{ __('Libra Law Firm') }}"
|
||||
{{ $attributes->merge(['class' => $sizes[$size]]) }}
|
||||
/>
|
||||
<div {{ $attributes->merge(['class' => 'flex items-center gap-2 p-5']) }}>
|
||||
<img
|
||||
src="{{ asset('images/' . $logoFile) }}"
|
||||
alt="{{ __('Libra Law Firm') }}"
|
||||
class="{{ $sizeClass }} w-auto object-contain"
|
||||
onerror="this.onerror=null; this.src='{{ asset('images/logo.png') }}';"
|
||||
/>
|
||||
@if($showText)
|
||||
<span class="font-semibold text-sm truncate">{{ __('Libra Law Firm') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
```
|
||||
|
||||
### Logo Asset Fallback Strategy
|
||||
If final logo assets are not yet available:
|
||||
1. Create a placeholder SVG using Libra scales icon from Heroicons or similar
|
||||
2. Use the brand colors (Gold #D4AF37, Navy #0A1F44)
|
||||
3. Replace with final assets when provided
|
||||
|
||||
### Color Reference (from Story 9.1)
|
||||
| Color | Hex | Usage |
|
||||
|-------|-----|-------|
|
||||
| Dark Navy Blue | #0A1F44 | Primary background |
|
||||
| Gold/Brass | #D4AF37 | Primary accent, logo |
|
||||
| Off-White/Cream | #F9F7F4 | Light backgrounds |
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Unit Tests
|
||||
Create `tests/Feature/Components/LogoComponentTest.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use function Pest\Laravel\get;
|
||||
|
||||
test('logo component renders with default props', function () {
|
||||
$view = $this->blade('<x-app-logo />');
|
||||
|
||||
$view->assertSee('Libra Law Firm');
|
||||
$view->assertSee('logo.svg');
|
||||
});
|
||||
|
||||
test('logo component renders small size variant', function () {
|
||||
$view = $this->blade('<x-app-logo size="small" />');
|
||||
|
||||
$view->assertSee('h-8');
|
||||
});
|
||||
|
||||
test('logo component renders reversed color variant', function () {
|
||||
$view = $this->blade('<x-app-logo variant="reversed" />');
|
||||
|
||||
$view->assertSee('logo-reversed.svg');
|
||||
});
|
||||
|
||||
test('logo component renders without text when showText is false', function () {
|
||||
$view = $this->blade('<x-app-logo :showText="false" />');
|
||||
|
||||
$view->assertDontSee('<span');
|
||||
});
|
||||
|
||||
test('logo has accessible alt text', function () {
|
||||
$view = $this->blade('<x-app-logo />');
|
||||
|
||||
$view->assertSee('alt="Libra Law Firm"', false);
|
||||
});
|
||||
```
|
||||
|
||||
### Browser Tests (Pest v4)
|
||||
Create `tests/Browser/LogoTest.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
it('displays logo in navigation on desktop', function () {
|
||||
$page = visit('/');
|
||||
|
||||
$page->assertVisible('img[alt="Libra Law Firm"]')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('logo is responsive on mobile viewport', function () {
|
||||
$page = visit('/')
|
||||
->viewport(375, 812); // iPhone viewport
|
||||
|
||||
$page->assertVisible('img[alt="Libra Law Firm"]');
|
||||
});
|
||||
```
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Logo displays in navigation
|
||||
- [ ] Logo displays in footer
|
||||
- [ ] Logo in email templates
|
||||
- [ ] Responsive sizing works
|
||||
- [ ] All color variants available
|
||||
- [ ] Alt text correct
|
||||
- [ ] Tests pass
|
||||
- [ ] Logo component created with size and variant props
|
||||
- [ ] Logo displays correctly in navigation header
|
||||
- [ ] All three color variants available and working
|
||||
- [ ] PNG fallback works when SVG fails to load
|
||||
- [ ] Responsive sizing works across breakpoints
|
||||
- [ ] Alt text is present and translatable
|
||||
- [ ] Existing header.blade.php updated to use new component
|
||||
- [ ] Unit tests pass
|
||||
- [ ] Browser tests pass
|
||||
- [ ] Code formatted with Pint
|
||||
|
||||
## Out of Scope (Deferred)
|
||||
- Footer logo placement → Story 9.7
|
||||
- Email template logo → Epic 8 (Story 8.1+)
|
||||
- PDF export logo → Future story
|
||||
|
||||
## Estimation
|
||||
**Complexity:** Low | **Effort:** 2 hours
|
||||
**Complexity:** Low | **Effort:** 2-3 hours
|
||||
|
||||
Reference in New Issue
Block a user