← back to Wine Finder Next

COMPONENT_IMPROVEMENTS_QUICK_REF.md

433 lines

# Component Improvements Quick Reference

## Component Structure

### Main Page Component
**File:** `/app/membership/page.tsx`

```
MembershipPage
├── LoadingSkeleton (while loading)
├── JsonLd (SEO structured data)
├── Header (sticky, with info cards)
├── Navigation (4 tabs with keyboard support)
├── Content Tabs
│   ├── BottlesTab
│   ├── VotingTab
│   ├── MarketplaceTab
│   └── MyHoldingsTab
└── Footer (SEO info)
```

## Key Improvements by Component

### 1. LoadingSkeleton Component
**Location:** `/components/membership/LoadingSkeleton.tsx`

**Purpose:** Show realistic loading state

**Features:**
- Animated pulse effects
- Matches final layout
- Zero layout shift
- Improves perceived performance

**Usage:**
```tsx
if (loading) {
  return <LoadingSkeleton />;
}
```

### 2. Header Component (Enhanced)

**Improvements:**
- Sticky positioning (`sticky top-0 z-50`)
- Better backdrop blur (`backdrop-blur-md`)
- Responsive padding (`px-4 sm:px-6 lg:px-8`)
- Slide-down animation on load
- Responsive info cards (1/2/3 columns)

**Key Classes:**
```css
.header {
  @apply bg-black/30 backdrop-blur-md border-b border-white/10;
  @apply sticky top-0 z-50;
  @apply transition-all duration-300;
}
```

### 3. Navigation Tabs (Enhanced)

**Improvements:**
- Keyboard navigation support (Enter/Space)
- Focus indicators
- ARIA labels and current state
- Scale animation on active state
- Mobile-friendly icons

**Accessibility:**
```tsx
<button
  aria-label="View bottles section"
  aria-current={selectedTab === 'bottles' ? 'page' : undefined}
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      setSelectedTab('bottles');
    }
  }}
  className="focus:outline-none focus:ring-2 focus:ring-purple-400"
>
```

### 4. BottlesTab Component (Enhanced)

**Card Features:**
- Staggered entrance animations
- Hover scale effect
- Animated progress bars
- Semantic HTML (article, itemScope)
- Responsive grid (1/2/3 columns)

**Progress Bar:**
```tsx
<div
  className="h-full bg-gradient-to-r from-purple-500 to-pink-500
    transition-all duration-1000 ease-out"
  style={{ width: `${fundingProgress}%` }}
  role="progressbar"
  aria-valuenow={fundingProgress}
  aria-valuemin={0}
  aria-valuemax={100}
  aria-label={`${fundingProgress.toFixed(1)}% funded`}
/>
```

### 5. VotingTab Component (Enhanced)

**Features:**
- Enhanced progress bars with double borders
- Better contrast for accessibility
- Loading states during submission
- Fieldset/legend for vote choices
- Responsive stats grid (2/4 columns)

**Vote Interface:**
```tsx
{selectedVote === vote.id ? (
  <div className="bg-black/20 p-4 rounded-lg space-y-3">
    <input
      id={`membership-id-${vote.id}`}
      type="text"
      style={{ fontSize: '16px' }} // Prevent iOS zoom
      className="focus:ring-2 focus:ring-purple-400"
      aria-required="true"
    />
    <fieldset>
      <legend className="sr-only">Choose your vote</legend>
      {/* Vote choices */}
    </fieldset>
  </div>
) : (
  <button>Cast Your Vote</button>
)}
```

### 6. MarketplaceTab Component (Enhanced)

**Features:**
- Loading state per listing
- Disabled states during purchase
- Staggered card animations
- Empty state message

**Purchase Button:**
```tsx
<button
  onClick={() => handlePurchase(listing.id)}
  disabled={isPurchasingThis}
  className="transform hover:scale-105 disabled:opacity-50"
>
  {isPurchasingThis ? 'Processing...' : 'Purchase Wine Share'}
</button>
```

### 7. MyHoldingsTab Component

**Features:**
- Centered layout
- Connect wallet CTA
- Responsive text sizing

## CSS Class Patterns

### Responsive Spacing
```css
/* Padding */
px-4 sm:px-6 lg:px-8

/* Gaps */
gap-3 sm:gap-4

/* Margins */
mb-4 sm:mb-6
```

### Responsive Typography
```css
/* Headers */
text-3xl sm:text-4xl

/* Body */
text-base sm:text-lg

/* Small */
text-xs sm:text-sm
```

### Responsive Grids
```css
/* Bottles */
grid-cols-1 md:grid-cols-2 lg:grid-cols-3

/* Stats */
grid-cols-2 lg:grid-cols-4

/* Marketplace */
grid-cols-1 md:grid-cols-2
```

### Animation Classes
```css
/* Entrance */
animate-fade-in
animate-slide-up
animate-slide-down
animate-scale-in

/* Loading */
animate-pulse
```

### Hover States
```css
/* Scale */
transform hover:scale-105

/* Shadow */
shadow-lg hover:shadow-xl

/* Background */
hover:bg-white/20
```

### Focus States
```css
focus:outline-none
focus:ring-2
focus:ring-purple-400
focus:ring-offset-2
focus:ring-offset-purple-900
```

## Accessibility Patterns

### ARIA Labels
```tsx
// Section labels
<section aria-label="Available wine bottles">

// Button labels
<button aria-label={`Buy shares of ${bottle.name}`}>

// Status indicators
<span role="status" aria-label={`Status: ${bottle.status}`}>
```

### Screen Reader Only
```tsx
<span className="sr-only">Membership Unit ID</span>
<label htmlFor="input-id" className="sr-only">
```

### Progress Indicators
```tsx
<div
  role="progressbar"
  aria-valuenow={percentage}
  aria-valuemin={0}
  aria-valuemax={100}
  aria-label={`${percentage}% complete`}
/>
```

### Form Controls
```tsx
<input
  id="unique-id"
  aria-required="true"
  aria-describedby="help-text"
/>

<fieldset>
  <legend className="sr-only">Choose option</legend>
  {/* Controls */}
</fieldset>
```

## Performance Patterns

### Memoization
```tsx
// Memoize expensive computations
const tabs = useMemo(() => [
  { id: 'bottles', label: 'Investment Bottles' },
  // ...
], []);

// Memoize callbacks
const loadData = useCallback(async () => {
  // ...
}, []);
```

### Parallel Fetching
```tsx
const [bottlesRes, votesRes, marketRes] = await Promise.all([
  fetch('/api/membership/bottles'),
  fetch('/api/membership/votes?active=true'),
  fetch('/api/membership/marketplace?active=true')
]);
```

### Staggered Animations
```tsx
{bottles.map((bottle, index) => (
  <article
    style={{ animationDelay: `${index * 100}ms` }}
    className="animate-scale-in"
  >
))}
```

## Mobile Optimization

### iOS Input Fix
```tsx
<input
  type="text"
  style={{ fontSize: '16px' }} // Prevents auto-zoom
  className="..."
/>
```

### Touch Targets
```css
/* Minimum 44px height for touch */
py-3  /* 0.75rem * 2 + line-height = ~44px */
```

### Flexible Layouts
```css
/* Flex direction changes */
flex-col sm:flex-row

/* Hide/show content */
hidden sm:block
sm:hidden
```

## Color Contrast

### Text on Dark Background
```css
text-white         /* 21:1 - AAA */
text-gray-300      /* 11:1 - AAA */
text-gray-400      /*  8:1 - AA */
```

### Status Colors
```css
/* Success */
bg-green-500/20 text-green-300 border-green-500/50

/* Warning */
bg-yellow-500/20 text-yellow-300 border-yellow-500/50

/* Error */
bg-red-500/20 text-red-300 border-red-500/50
```

## Testing Commands

### Start Server
```bash
pm2 restart wine-finder-next
```

### View Logs
```bash
pm2 logs wine-finder-next
```

### Test Page
```bash
curl -I http://45.61.58.125:7250/membership
```

### Lighthouse Audit
```bash
npx lighthouse http://45.61.58.125:7250/membership --view
```

## Common Issues & Solutions

### Issue: iOS Auto-Zoom on Input
**Solution:** Set `fontSize: '16px'` inline style

### Issue: Layout Shift on Load
**Solution:** Use LoadingSkeleton with matching layout

### Issue: Poor Focus Visibility
**Solution:** Add `focus:ring-2 focus:ring-purple-400`

### Issue: Touch Targets Too Small
**Solution:** Minimum `py-3` padding (44px total)

### Issue: Animation Lag
**Solution:** Use `transform` and `opacity` only (GPU accelerated)

### Issue: Accessibility Warnings
**Solution:** Add proper ARIA labels and semantic HTML

## Browser Support

### Tested Browsers
- Chrome 120+ ✅
- Firefox 121+ ✅
- Safari 17+ ✅
- Edge 120+ ✅
- Mobile Safari (iOS 16+) ✅
- Chrome Mobile (Android 12+) ✅

### Polyfills Needed
- None (using modern Next.js features)

## Deployment Checklist

- [x] All components load without errors
- [x] Responsive design works on all breakpoints
- [x] Animations are smooth (60fps)
- [x] Accessibility features implemented
- [x] Loading skeleton prevents layout shift
- [x] Color contrast meets WCAG AA
- [x] Keyboard navigation works
- [x] Focus indicators visible
- [x] ARIA labels present
- [x] Mobile touch targets adequate
- [x] iOS input zoom prevented
- [ ] Images optimized (future)
- [ ] Performance metrics monitored
- [ ] Analytics integrated (future)