- Design two-column flexbox layout (label left, number right) - Responsive font sizing (sm/md/lg breakpoints) - Label truncation for long text - Applies to Inventory, Logs, and Admin pages - Ready for implementation review
7.9 KiB
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-betweenwith 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:
interface StatCard {
label: string; // e.g., "Categories", "Total Events"
value: number; // e.g., 2, 42
icon?: React.ReactNode; // Optional icon (Lucide)
}
Markup Structure:
<div className="flex justify-between items-center gap-2 p-4 bg-slate-900 rounded-lg">
{/* Icon + Label Container */}
<div className="flex items-center gap-2 min-w-0">
{icon && <Icon className="w-5 h-5 text-primary" />}
<span className="text-sm md:text-base text-slate-400 truncate">
{label}
</span>
</div>
{/* Number (Right) */}
<span className="text-lg md:text-xl font-black text-white whitespace-nowrap">
{value}
</span>
</div>
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:
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)
<div className="flex gap-4">
<div className="flex items-center gap-2">
<Layers className="text-primary" />
<div>
<p className="text-xs text-slate-500">Categories</p>
<p className="text-lg font-black">{categoriesCount}</p>
</div>
</div>
</div>
Updated Implementation:
<div className="flex justify-between items-center gap-2 p-4 bg-slate-900 rounded-lg">
<div className="flex items-center gap-2 min-w-0">
<Layers className="w-5 h-5 text-primary" />
<span className="text-sm md:text-base text-slate-400 truncate">
Categories
</span>
</div>
<span className="text-lg md:text-xl font-black text-white whitespace-nowrap">
{categoriesCount}
</span>
</div>
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:
<span className="text-sm md:text-base text-slate-400 truncate">
Total Events in System
</span>
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-nowrapprevents wraptext-lg md:text-xlscales 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
StatCardcomponent 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)