fix(responsive): prevent horizontal overflow on mobile
Some checks failed
Visual diff / Should run? (pull_request) Has been cancelled
CI / Lint (pull_request) Has been cancelled
CI / Schema map up to date (pull_request) Has been cancelled
CI / Forbidden patterns (9 checks) (pull_request) Has been cancelled
CI / Migrations apply (node-pg-migrate) (pull_request) Has been cancelled
CI / Unit tests (vitest) (pull_request) Has been cancelled
Convoy metrics gate / Require role-event telemetry on convoy PRs (pull_request) Has been cancelled
PR Health rollup / Aggregate gate status (pull_request) Has been cancelled
Preview smoke / Should run? (pull_request) Has been cancelled
Visual diff / Screenshot diff (pull_request) Has been cancelled
Preview smoke / Playwright smoke (pull_request) Has been cancelled

- styles/globals.css: add overflow-x: hidden + max-width: 100vw to body (global safety net)
- components/CollectionPageView.js: flex-wrap filter row, responsive search width (w-full sm:w-64)
- pages/my-cards.js: replace min-w-[200px] with w-full sm:min-w-[200px] on filter search
- pages/designer.js: remove shrink-0 from live preview sidebar to allow flex collapse
- components/DeckDetailView.js: add flex-wrap + gap to header flex row
- components/CardItem.js: remove whitespace-nowrap from expanding add buttons (3 instances)
- components/DashboardRecentActivity.js: whitespace-nowrap → whitespace-normal on timestamp
- components/CollaboratorFacepile.js: tooltips use whitespace-normal + break-words + max-w
- components/MobileNavigation.js: tooltip whitespace-nowrap → whitespace-normal

Fixes horizontal scroll / layout breakage on mobile (<375px) across the site.
This commit is contained in:
Randall Stillwell 2026-09-11 17:55:30 -05:00
parent 3dc9b5852f
commit e6869c82cc
9 changed files with 17 additions and 15 deletions

View file

@ -31,7 +31,7 @@ function ExpandingAddButton({ card, onAddToCollection, onAddToDeck, onMarkAsOwne
<div className="absolute bottom-full left-0 mb-1 flex flex-col space-y-1">
<button
onClick={(e) => handleOptionClick(e, () => onAddToCollection([card]))}
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs whitespace-nowrap"
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs"
style={{ backgroundColor: 'var(--accent-flame)', color: 'white' }}
title={VOCAB.ADD_TO_LIST}
>
@ -43,7 +43,7 @@ function ExpandingAddButton({ card, onAddToCollection, onAddToDeck, onMarkAsOwne
<button
onClick={(e) => handleOptionClick(e, () => onAddToDeck([card]))}
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs whitespace-nowrap"
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs"
style={{ backgroundColor: 'var(--accent-gold)', color: 'white' }}
title="Add to Deck"
>
@ -55,7 +55,7 @@ function ExpandingAddButton({ card, onAddToCollection, onAddToDeck, onMarkAsOwne
<button
onClick={(e) => handleOptionClick(e, onMarkAsOwned)}
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs whitespace-nowrap"
className="p-1.5 rounded-md shadow-lg transition-all duration-150 hover:scale-105 flex items-center space-x-1 text-xs"
style={{ backgroundColor: 'var(--accent-ember)', color: 'white' }}
title={VOCAB.ADD_TO_MY_COLLECTION}
>

View file

@ -101,7 +101,7 @@ export default function CollaboratorFacepile({ collectionId, creatorEmail }) {
{/* Tooltip */}
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
<div className="bg-gray-900 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap">
<div className="bg-gray-900 text-white text-xs rounded-lg py-2 px-3 whitespace-normal break-words max-w-[12rem]">
<div className="font-medium">{user.email}</div>
<div className="text-gray-300">{getRoleLabel(user.role)}</div>
{/* Arrow */}
@ -119,7 +119,7 @@ export default function CollaboratorFacepile({ collectionId, creatorEmail }) {
{/* Tooltip for remaining users */}
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-20">
<div className="bg-gray-900 text-white text-xs rounded-lg py-2 px-3 whitespace-nowrap max-w-48">
<div className="bg-gray-900 text-white text-xs rounded-lg py-2 px-3 whitespace-normal break-words max-w-[12rem] max-w-48">
<div className="font-medium mb-1">{remainingCount} more collaborator{remainingCount > 1 ? 's' : ''}</div>
{allUsers.slice(4).map((user, index) => (
<div key={user.email || index} className="text-gray-300">

View file

@ -183,7 +183,7 @@ export default function CollectionPageView(props) {
</p>
{/* TCG Tags */}
<div className="flex items-center space-x-2 mb-4">
<div className="flex flex-wrap items-center gap-2 mb-4">
{Object.entries(gameStats).map(([game, count]) =>
count > 0 ? (
<span
@ -287,9 +287,9 @@ export default function CollectionPageView(props) {
{/* Content */}
<div className="p-6">
{/* Search and Filters */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center space-x-4">
<div className="w-64">
<div className="flex flex-wrap items-center justify-between gap-3 mb-6">
<div className="flex flex-wrap items-center gap-3 w-full sm:w-auto">
<div className="w-full sm:w-64">
<SearchBar
value={searchCards}
onChange={(e) => {
@ -307,7 +307,7 @@ export default function CollectionPageView(props) {
<select
value={selectedRarity}
onChange={(e) => setSelectedRarity(e.target.value)}
className="input-field"
className="input-field w-full sm:w-auto"
>
<option>All Rarities</option>
<option>Common</option>

View file

@ -88,7 +88,7 @@ export default function DashboardRecentActivity({ activities = [], loading = fal
</div>
</div>
<span
className="text-xs whitespace-nowrap flex-shrink-0"
className="text-xs whitespace-normal flex-shrink-0"
style={{ color: 'var(--text-secondary)' }}
>
{row.time}

View file

@ -14,7 +14,7 @@ export default function DeckDetailView({
}) {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="flex justify-between items-start mb-8">
<div className="flex flex-wrap justify-between items-start mb-8 gap-3">
<div>
<div className="flex items-center space-x-3 mb-2">
<Link

View file

@ -130,7 +130,7 @@ export default function MobileNavigation({ onMenuOpen }) {
{getIcon(item.icon, item.active, true)}
</button>
<span
className="absolute top-12 left-1/2 transform -translate-x-1/2 text-xs font-medium whitespace-nowrap"
className="absolute top-12 left-1/2 transform -translate-x-1/2 text-xs font-medium whitespace-normal"
style={{
color: item.active
? 'var(--accent-ember)'

View file

@ -898,7 +898,7 @@ export default function Designer() {
</div>
)}
</div>
<div className="w-full max-w-[240px] shrink-0">
<div className="w-full max-w-[240px]">
<p className="text-xs mb-2 text-center" style={{ color: 'var(--text-secondary)' }}>
Live frame preview
</p>

View file

@ -352,7 +352,7 @@ export default function MyCards() {
<div>
<div className="glass-panel rounded-2xl p-4 mb-6">
<div className="flex flex-wrap gap-4">
<div className="flex-1 min-w-[200px]">
<div className="flex-1 w-full sm:min-w-[200px]">
<SearchBar
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}

View file

@ -10,6 +10,8 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transition: background-color 0.3s ease, color 0.3s ease;
overflow-x: hidden;
max-width: 100vw;
}
/* Theme Variables - Deck Hearth Fire-Inspired */