Files
breedr/docs/COMPACT_CARDS.md

324 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
<Link to={`/dogs/${dog.id}`} className="card">
{/* Avatar */}
<div className="avatar-80">
{photo ? <img src={photo} /> : <Dog icon />}
</div>
{/* Info */}
<div className="info-section">
<h3>{name} <span>{sex icon}</span></h3>
<div className="metadata">
{breed} {age} {color}
</div>
<div className="badge">
<Hash /> {registration}
</div>
</div>
{/* Arrow */}
<ArrowRight />
</Link>
```
### 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*