From 48d1b1b5f9b706f3f1ce2dddb17e761b64204af8 Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Sat, 26 Jul 2025 00:49:42 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=B1=20Implement=20Mobile-First=20Respo?= =?UTF-8?q?nsive=20Design?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 Mobile Slide-In Navigation: - Added mobile menu button with hamburger icon - Implemented slide-in sidebar with smooth transitions - Added mobile overlay with click-to-close functionality - Mobile menu auto-closes when navigating to new pages - Proper z-index layering for mobile interactions 🃏 Smart Card Panel Positioning: - Panels now open on opposite side for right-edge cards - Added cardIndex and cardsPerRow props to CardItem - Dynamic positioning based on card's position in grid - Prevents panels from extending off-screen edges - Maintains hover functionality on desktop 📱 Mobile-Optimized Bulk Actions: - Toolbar now spans full width on mobile devices - Icon-only buttons on mobile, full labels on desktop - Responsive spacing and padding adjustments - Improved touch targets for mobile interaction - Maintains functionality across all screen sizes 🎨 Enhanced Grid Layout: - Improved mobile grid: 2 columns with tighter spacing - Better space utilization on all device sizes - Responsive gap spacing that adapts to screen size - Optimized padding for mobile vs desktop - Cards now fill available space properly ✅ Cross-Device Experience: - Mobile: Slide-in nav, icon-only actions, 2-column grid - Tablet: Responsive layout with appropriate spacing - Desktop: Full sidebar, labeled actions, hover panels - Large screens: Maximum columns with side panel space The app now provides an optimal mobile experience while maintaining desktop functionality! ��💻🖥️ --- components/BulkSelectionToolbar.js | 27 ++++++++-------- components/CardItem.js | 18 +++++++++-- components/Layout.js | 51 ++++++++++++++++++++++++++++-- pages/cards.js | 42 ++++++++++++++++-------- 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/components/BulkSelectionToolbar.js b/components/BulkSelectionToolbar.js index b2cbf10..e2d47c6 100644 --- a/components/BulkSelectionToolbar.js +++ b/components/BulkSelectionToolbar.js @@ -42,51 +42,52 @@ export default function BulkSelectionToolbar({ }; return ( -
-
+
+
{/* Selection Count */}
{selectedCount}
- - {selectedCount} card{selectedCount !== 1 ? 's' : ''} selected + + {selectedCount} card{selectedCount !== 1 ? 's' : ''} selected + {selectedCount}
- {/* Divider */} -
+ {/* Divider - Hidden on mobile */} +
{/* Quick Actions */} -
+
diff --git a/components/CardItem.js b/components/CardItem.js index 1bfd0aa..909cb7a 100644 --- a/components/CardItem.js +++ b/components/CardItem.js @@ -9,7 +9,9 @@ export default function CardItem({ onAddToCollection, onAddToDeck, onToggleFavorite, - isFavorited = false + isFavorited = false, + cardIndex = 0, + cardsPerRow = 4 }) { const [imageError, setImageError] = useState(false); const router = useRouter(); @@ -75,6 +77,10 @@ export default function CardItem({ const rarityEffects = getRarityEffects(card.rarity); + // Determine panel position based on card position in row + const isRightSide = (cardIndex % cardsPerRow) >= Math.floor(cardsPerRow / 2); + const panelPosition = isRightSide ? 'right' : 'left'; + if (viewMode === 'list') { return (
{/* Side Hover Panel */} -
+ {/* Mobile Menu Button */} + + + {/* Mobile Overlay */} + {isMobileMenuOpen && ( +
setIsMobileMenuOpen(false)} + /> + )} + {/* Left Sidebar */} -
+
-
+ {/* Mobile Close Button */} +
+
+
+ TCG +
+

TCG Vault

+
+ +
+ + {/* Desktop Header */} +
TCG
@@ -110,6 +153,7 @@ export default function Layout({ children, user = { email: 'me@randallstillwell. backgroundColor: item.active ? 'var(--bg-tertiary)' : 'transparent', color: item.active ? 'var(--text-primary)' : 'var(--text-secondary)' }} + onClick={() => setIsMobileMenuOpen(false)} >
{getIcon(item.icon)} @@ -178,6 +222,7 @@ export default function Layout({ children, user = { email: 'me@randallstillwell. backgroundColor: item.active ? 'var(--bg-tertiary)' : 'transparent', color: item.active ? 'var(--text-primary)' : 'var(--text-secondary)' }} + onClick={() => setIsMobileMenuOpen(false)} > {getIcon(item.icon)} {item.name} @@ -190,7 +235,7 @@ export default function Layout({ children, user = { email: 'me@randallstillwell.
{/* Main Content */} -
+
{/* Top Header - Only show search on dashboard */} {showSearch && (
diff --git a/pages/cards.js b/pages/cards.js index 497d40d..bf5dae3 100644 --- a/pages/cards.js +++ b/pages/cards.js @@ -816,20 +816,34 @@ export default function Cards() {
) : ( <> -
- {cards.map(card => ( - c.id === card.id)} - onToggleSelect={handleToggleSelect} - onAddToCollection={(card) => handleBulkAddToCollection([card])} - onAddToDeck={handleBulkAddToDeck} - onToggleFavorite={handleToggleFavorite} - isFavorited={favoritedCards.has(card.id)} - /> - ))} +
+ {cards.map((card, index) => { + // Calculate cards per row based on current breakpoint + const getCardsPerRow = () => { + if (window.innerWidth >= 1536) return 5; // 2xl + if (window.innerWidth >= 1280) return 4; // xl + if (window.innerWidth >= 1024) return 3; // lg + if (window.innerWidth >= 768) return 4; // md + if (window.innerWidth >= 640) return 3; // sm + return 2; // base + }; + + return ( + c.id === card.id)} + onToggleSelect={handleToggleSelect} + onAddToCollection={(card) => handleBulkAddToCollection([card])} + onAddToDeck={handleBulkAddToDeck} + onToggleFavorite={handleToggleFavorite} + isFavorited={favoritedCards.has(card.id)} + cardIndex={index} + cardsPerRow={getCardsPerRow()} + /> + ); + })}
{/* Infinite Scroll Loading Indicator */}