fix(responsive): prevent horizontal overflow on mobile #159

Merged
rstillwell merged 2 commits from fix/mobile-overflow into main 2026-09-11 21:06:53 -04:00
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"> <div className="absolute bottom-full left-0 mb-1 flex flex-col space-y-1">
<button <button
onClick={(e) => handleOptionClick(e, () => onAddToCollection([card]))} 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' }} style={{ backgroundColor: 'var(--accent-flame)', color: 'white' }}
title={VOCAB.ADD_TO_LIST} title={VOCAB.ADD_TO_LIST}
> >
@ -43,7 +43,7 @@ function ExpandingAddButton({ card, onAddToCollection, onAddToDeck, onMarkAsOwne
<button <button
onClick={(e) => handleOptionClick(e, () => onAddToDeck([card]))} 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' }} style={{ backgroundColor: 'var(--accent-gold)', color: 'white' }}
title="Add to Deck" title="Add to Deck"
> >
@ -55,7 +55,7 @@ function ExpandingAddButton({ card, onAddToCollection, onAddToDeck, onMarkAsOwne
<button <button
onClick={(e) => handleOptionClick(e, onMarkAsOwned)} 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' }} style={{ backgroundColor: 'var(--accent-ember)', color: 'white' }}
title={VOCAB.ADD_TO_MY_COLLECTION} title={VOCAB.ADD_TO_MY_COLLECTION}
> >

View file

@ -101,7 +101,7 @@ export default function CollaboratorFacepile({ collectionId, creatorEmail }) {
{/* Tooltip */} {/* 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="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="font-medium">{user.email}</div>
<div className="text-gray-300">{getRoleLabel(user.role)}</div> <div className="text-gray-300">{getRoleLabel(user.role)}</div>
{/* Arrow */} {/* Arrow */}
@ -119,7 +119,7 @@ export default function CollaboratorFacepile({ collectionId, creatorEmail }) {
{/* Tooltip for remaining users */} {/* 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="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> <div className="font-medium mb-1">{remainingCount} more collaborator{remainingCount > 1 ? 's' : ''}</div>
{allUsers.slice(4).map((user, index) => ( {allUsers.slice(4).map((user, index) => (
<div key={user.email || index} className="text-gray-300"> <div key={user.email || index} className="text-gray-300">

View file

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

View file

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

View file

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

View file

@ -130,7 +130,7 @@ export default function MobileNavigation({ onMenuOpen }) {
{getIcon(item.icon, item.active, true)} {getIcon(item.icon, item.active, true)}
</button> </button>
<span <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={{ style={{
color: item.active color: item.active
? 'var(--accent-ember)' ? 'var(--accent-ember)'

View file

@ -898,7 +898,7 @@ export default function Designer() {
</div> </div>
)} )}
</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)' }}> <p className="text-xs mb-2 text-center" style={{ color: 'var(--text-secondary)' }}>
Live frame preview Live frame preview
</p> </p>

View file

@ -356,7 +356,7 @@ export default function MyCards() {
<div> <div>
<div className="glass-panel rounded-2xl p-4 mb-6"> <div className="glass-panel rounded-2xl p-4 mb-6">
<div className="flex flex-wrap gap-4"> <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 <SearchBar
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}

View file

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