# Compact Info Card Design ## Problem Statement The original design used large square photo grids that consumed excessive screen space, making it difficult to scan through multiple dogs quickly. Photos were displayed at 1:1 aspect ratio taking up 50-100% of card width. ## Solution: Horizontal Info Cards Transformed to a **compact horizontal card layout** with small avatar photos and prominent metadata, optimized for information scanning and list navigation. --- ## Design Specifications ### Layout Structure ``` ┌─────────────────────────────────────────────────────────────────┐ │ [Avatar] Name ♂ Breed • Age • Color → │ │ 80x80 Golden Retriever #REG-12345 │ └─────────────────────────────────────────────────────────────────┘ ``` ### Card Components #### 1. Avatar Photo (80x80px) - **Size:** Fixed 80px × 80px - **Shape:** Rounded corners (var(--radius)) - **Border:** 2px solid var(--border) - **Background:** var(--bg-primary) when no photo - **Fallback:** Dog icon at 32px, muted color - **Object Fit:** cover (crops to fill square) #### 2. Info Section (Flex: 1) - **Name:** 1.125rem, bold, truncate with ellipsis - **Sex Icon:** Colored ♂/♀ (blue for male, pink for female) - **Metadata Row:** - Breed name - Age (calculated, with calendar icon) - Color (if available) - Separated by bullets (•) - **Registration Badge:** - Monospace font - Hash icon prefix - Dark background pill - 1px border #### 3. Arrow Indicator - **Icon:** ArrowRight at 20px - **Color:** var(--text-muted) - **Opacity:** 0.5 default, increases on hover - **Purpose:** Visual affordance for clickability --- ## Space Comparison ### Before (Square Grid) ``` [===============] [ Photo ] [ 300x300 ] [===============] Name Breed • Sex ``` **Height:** ~380px per card **Width:** 280-300px **Photos per viewport:** 2-3 (desktop) ### After (Horizontal Card) ``` [Avatar] Name, Breed, Age, Badge → 80x80 ``` **Height:** ~100px per card **Width:** Full container width **Cards per viewport:** 6-8 (desktop) ### Metrics | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | Card height | 380px | 100px | **-74%** | | Photo area | 90,000px² | 6,400px² | **-93%** | | Scannable info | 2-3 cards | 6-8 cards | **+200%** | | Scroll distance | 760px | 200px | **-74%** | --- ## Implementation Details ### React Component Structure ```jsx {/* Avatar */}
{photo ? : }
{/* Info */}

{name} {sex icon}

{breed} • {age} • {color}
{registration}
{/* Arrow */} ``` ### CSS Styling ```css .card { display: flex; gap: 1rem; align-items: center; padding: 1rem; transition: all 0.2s; } .card:hover { border-color: var(--primary); transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0,0,0,0.3); } .avatar-80 { width: 80px; height: 80px; border-radius: var(--radius); border: 2px solid var(--border); overflow: hidden; } .info-section { flex: 1; min-width: 0; /* Allow text truncation */ } ``` --- ## Age Calculation Dynamic age display from birth date: ```javascript const calculateAge = (birthDate) => { const today = new Date() const birth = new Date(birthDate) let years = today.getFullYear() - birth.getFullYear() let months = today.getMonth() - birth.getMonth() if (months < 0) { years-- months += 12 } // Format: "2y 3mo" or "8mo" or "3y" if (years === 0) return `${months}mo` if (months === 0) return `${years}y` return `${years}y ${months}mo` } ``` --- ## Interactive States ### Default - Border: var(--border) - Shadow: var(--shadow-sm) - Transform: none ### Hover - Border: var(--primary) - Shadow: 0 8px 16px rgba(0,0,0,0.3) - Transform: translateY(-2px) - Arrow opacity: 1.0 - Transition: 0.2s cubic-bezier ### Active/Click - Navigate to detail page - Maintains selection state in history --- ## Responsive Behavior ### Desktop (>768px) - Full horizontal layout - All metadata visible - Hover effects enabled ### Tablet (768px - 1024px) - Slightly smaller avatar (70px) - Abbreviated metadata - Touch-friendly spacing ### Mobile (<768px) - Avatar: 60px - Name on top line - Metadata stacks below - Registration badge wraps - Larger tap targets --- ## Accessibility ### Keyboard Navigation - Cards are focusable links - Tab order follows visual order - Enter/Space to activate - Focus ring with primary color ### Screen Readers - Semantic HTML (Link + heading structure) - Alt text on avatar images - Icon meanings in aria-labels - Registration formatted as code ### Color Contrast - Name: High contrast (var(--text-primary)) - Metadata: Medium contrast (var(--text-secondary)) - Icons: Sufficient contrast ratios - Sex icons: Color + symbol (not color-only) --- ## Benefits ### User Experience 1. **Faster Scanning** - See 3x more dogs without scrolling 2. **Quick Comparison** - All key info visible at once 3. **Less Cognitive Load** - Consistent layout, predictable 4. **Better Navigation** - Clear visual hierarchy ### Performance 1. **Smaller Images** - Avatar size reduces bandwidth 2. **Lazy Loading** - Efficient with IntersectionObserver 3. **Less Rendering** - Simpler DOM structure 4. **Faster Scrolling** - Fewer pixels to paint ### Mobile 1. **Touch Targets** - Full card width clickable 2. **Vertical Real Estate** - More content on screen 3. **Thumb-Friendly** - No precise tapping required 4. **Data Efficient** - Smaller photo downloads --- ## Usage Context ### Dashboard - Shows 6-8 recent dogs - "View All" button to Dogs page - Provides quick overview ### Dogs List - Full searchable/filterable catalog - Horizontal scroll on mobile - Infinite scroll potential - Batch operations possible ### NOT Used For - Dog detail page (uses full photo gallery) - Pedigree tree (uses compact nodes) - Print layouts (uses different format) --- ## Future Enhancements ### Planned - [ ] Checkbox selection mode (bulk actions) - [ ] Drag-to-reorder in custom lists - [ ] Quick actions menu (edit, delete) - [ ] Photo upload from card - [ ] Inline editing of name/breed ### Considered - Multi-select with Shift+Click - Card density options (compact/comfortable/spacious) - Alternative views (grid toggle) - Column sorting (name, age, breed) - Grouping (by breed, age range) --- ## Examples ### Example 1: Male with Photo ``` ┌───────────────────────────────────────────────────────────┐ │ [Photo] Max ♂ → │ │ Golden Retriever • 2y 3mo • Golden │ │ #AKC-SR123456 │ └───────────────────────────────────────────────────────────┘ ``` ### Example 2: Female No Photo ``` ┌───────────────────────────────────────────────────────────┐ │ [🐶] Bella ♀ → │ │ icon Labrador Retriever • 8mo • Black │ └───────────────────────────────────────────────────────────┘ ``` ### Example 3: Puppy No Registration ``` ┌───────────────────────────────────────────────────────────┐ │ [Photo] Rocky ♂ → │ │ German Shepherd • 3mo │ └───────────────────────────────────────────────────────────┘ ``` --- *Last Updated: March 8, 2026*