diff --git a/docs/superpowers/specs/2026-04-15-mobile-stat-cards-responsive-design.md b/docs/superpowers/specs/2026-04-15-mobile-stat-cards-responsive-design.md new file mode 100644 index 00000000..1fb570e4 --- /dev/null +++ b/docs/superpowers/specs/2026-04-15-mobile-stat-cards-responsive-design.md @@ -0,0 +1,262 @@ +# Mobile Stat Cards Responsive Design + +> **Goal:** Fix stat card content overflow on mobile iPhone screens by implementing a two-column flexbox layout (label left, number right) that adapts responsively across breakpoints. + +> **Architecture:** Redesign stat card components to use `flex justify-between` with responsive font sizing and label truncation. Apply fix to Inventory, Logs, and Admin pages. + +> **Tech Stack:** Tailwind CSS, React, Next.js 15, responsive breakpoints + +--- + +## 1. Problem Statement + +**Current Issue:** Stat cards display labels and numbers that overflow outside card boundaries on mobile screens (< 640px). + +**Affected Components:** +- Inventory Page: "Categories 2", "Item Types 6", "Total Boxes 2" +- Logs Page: "Total Events [number]" +- Admin Page: Stat displays with label + number pattern + +**Root Cause:** Cards use inline or block layout without proper space distribution, causing numbers to overflow when screen width is constrained. + +--- + +## 2. Solution Overview + +**Approach: Two-Column Flexbox Layout** + +Redesign stat cards using CSS Flexbox with: +- **Label (Left):** Flexible width, can grow to fill space, truncates if too long +- **Number (Right):** Fixed width, never wraps, always visible +- **Responsive Sizing:** Font sizes reduce on mobile (`text-sm`) and increase on desktop (`text-base`/`text-xl`) +- **Gap:** 8px (`gap-2`) breathing room between label and number + +**Layout Formula:** +``` +[Label (flexible)] [gap] [Number (fixed)] +``` + +--- + +## 3. Component Specification + +### 3.1 Stat Card Component + +**Component Name:** `StatCard` (or enhance existing stat display) + +**Props:** +```typescript +interface StatCard { + label: string; // e.g., "Categories", "Total Events" + value: number; // e.g., 2, 42 + icon?: React.ReactNode; // Optional icon (Lucide) +} +``` + +**Markup Structure:** +```tsx +
+ {/* Icon + Label Container */} +
+ {icon && } + + {label} + +
+ + {/* Number (Right) */} + + {value} + +
+``` + +**CSS Classes Breakdown:** +| Class | Purpose | +|-------|---------| +| `flex justify-between` | Label left, number right | +| `items-center` | Vertically center all items | +| `gap-2` | 8px spacing between label and number | +| `p-4` | Padding inside card (8px on mobile via Tailwind default) | +| `bg-slate-900` | Card background (dark theme) | +| `rounded-lg` | Rounded corners | +| `text-sm md:text-base` | Font size: 14px mobile, 16px desktop+ | +| `text-slate-400` | Label color (muted) | +| `truncate` | Label ellipsis if overflow (single line only) | +| `text-lg md:text-xl` | Number size: 18px mobile, 20px desktop+ | +| `font-black` | Number weight (bold) | +| `text-white` | Number color (high contrast) | +| `whitespace-nowrap` | Number never wraps to new line | +| `min-w-0` | Allow label container to shrink below content size (enables truncate) | + +--- + +## 4. Responsive Breakpoints + +**Mobile (< 640px):** +- Label: `text-sm` (14px) +- Number: `text-lg` (18px) +- Padding: `p-4` (16px all sides) +- Gap: `gap-2` (8px) + +**Tablet (640px - 1024px):** +- Label: `text-base` (16px) +- Number: `text-xl` (20px) +- Padding: `p-5` (20px all sides) + +**Desktop (> 1024px):** +- Label: `text-base` (16px) +- Number: `text-xl` (20px) +- Padding: `p-6` (24px all sides) + +**Tailwind Breakpoint Syntax:** +```tsx +className="text-sm md:text-base lg:text-base" // Label +className="text-lg md:text-xl lg:text-xl" // Number +className="p-4 md:p-5 lg:p-6" // Padding +``` + +--- + +## 5. Affected Pages & Components + +### 5.1 Inventory Page +**Location:** `frontend/app/inventory/page.tsx` (or relevant component) + +**Stat Cards to Fix:** +- Categories [count] +- Item Types [count] +- Total Boxes [count] + +**Current Implementation:** (likely) +```tsx +
+
+ +
+

Categories

+

{categoriesCount}

+
+
+
+``` + +**Updated Implementation:** +```tsx +
+
+ + + Categories + +
+ + {categoriesCount} + +
+``` + +### 5.2 Logs Page +**Location:** `frontend/app/logs/page.tsx` (or relevant component) + +**Stat Card to Fix:** +- Total Events [count] + +**Apply same two-column pattern.** + +### 5.3 Admin Page +**Location:** `frontend/app/admin/page.tsx` (or relevant component) + +**Stat Cards to Fix:** +- Any label + number displays + +**Apply same two-column pattern.** + +--- + +## 6. Edge Cases & Handling + +### 6.1 Long Labels +**Problem:** "Total Events in System" might be too long on mobile + +**Solution:** Use `truncate` class to show ellipsis: +```tsx + + Total Events in System + +``` + +Result on mobile: "Total Events in S..." (with ellipsis) + +### 6.2 Large Numbers (3+ digits) +**Problem:** "1234" might still overflow on very narrow screens + +**Solution:** +- `whitespace-nowrap` prevents wrap +- `text-lg md:text-xl` scales appropriately +- If a number is > 999, consider abbreviating: "1.2K" instead of "1234" + +### 6.3 Icon Presence/Absence +**Problem:** Some cards may have icons, some may not + +**Solution:** Icon is optional, layout still works: +- With icon: [icon] [label] [gap] [number] +- Without icon: [label] [gap] [number] + +Both center properly with `items-center` on the flex container. + +--- + +## 7. Testing Strategy + +### 7.1 Responsive Testing +- **iPhone SE (375px):** Verify no overflow, label truncates if needed +- **iPhone 12/13 (390px):** Verify alignment and spacing +- **iPhone 14 Pro Max (430px):** Verify layout stability +- **iPad (768px):** Verify desktop-like appearance with `md:` breakpoint +- **Desktop (1920px):** Verify `lg:` breakpoint works + +### 7.2 Edge Cases +- Very long labels: "Total Events in System Very Long Name" +- Large numbers: 9999, 1234567 +- No icon present +- Icon + label + number all together + +### 7.3 Visual Regression +- Compare before/after on all three pages (Inventory, Logs, Admin) +- Verify card backgrounds, padding, and spacing remain consistent +- Verify typography hierarchy (label < number in weight/size) + +--- + +## 8. Files to Modify + +| File | Component(s) | Change | +|------|--------------|--------| +| `frontend/app/inventory/page.tsx` | Stat cards display | Apply two-column layout | +| `frontend/app/logs/page.tsx` | Stat cards display | Apply two-column layout | +| `frontend/app/admin/page.tsx` | Stat cards display | Apply two-column layout | +| `frontend/components/StatCard.tsx` | (Optional) New component | Create reusable StatCard component | + +--- + +## 9. Success Criteria + +✓ No content overflow on iPhone SE (375px) in portrait mode +✓ Labels and numbers both fully visible on mobile +✓ Labels truncate gracefully with ellipsis on very long text +✓ Numbers stay right-aligned without wrapping +✓ Responsive font sizes scale correctly across breakpoints (`sm`, `md`, `lg`) +✓ Visual consistency across Inventory, Logs, and Admin pages +✓ No regression on desktop/tablet layouts + +--- + +## 10. Implementation Notes + +- **Tailwind-first approach:** Use responsive utility classes, no custom CSS +- **Prefer composition:** Create reusable `StatCard` component if multiple pages share the pattern +- **Keep it DRY:** If stat cards are duplicated across pages, extract to shared component +- **Accessibility:** Ensure label and number have sufficient color contrast (WCAG AA) + +---