Skip to content

Commit 34812fd

Browse files
committed
fix: responsive stats row - wraps on mobile instead of hiding
Restructured result rows on /dht and /search: - Name row on top with buttons/thumbnail - Stats row below with flex-wrap, flows naturally on small screens - No fixed widths on stats, no overflow hidden, no hidden content - All info visible at every screen size
1 parent a00d4fd commit 34812fd

2 files changed

Lines changed: 119 additions & 124 deletions

File tree

src/app/dht/page.tsx

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -126,72 +126,68 @@ const DhtResultsList = memo(function DhtResultsList({
126126
}
127127

128128
return (
129-
<div className="space-y-1 overflow-x-hidden" style={{ textSizeAdjust: '100%', WebkitTextSizeAdjust: '100%' }}>
129+
<div className="space-y-1" style={{ textSizeAdjust: '100%', WebkitTextSizeAdjust: '100%' }}>
130130
{results.map((result) => (
131131
<Link
132132
key={result.infohash}
133133
href={`/dht/${result.infohash}`}
134134
className={cn(
135-
'flex items-center gap-3 rounded border border-transparent px-3 py-2',
135+
'block rounded border border-transparent px-3 py-2',
136136
'hover:border-accent-primary/30 hover:bg-bg-hover',
137137
'transition-colors'
138138
)}
139139
>
140-
{/* Add to Library button */}
141-
<button
142-
type="button"
143-
onClick={(e) => {
144-
e.preventDefault();
145-
e.stopPropagation();
146-
onAddToLibrary(result);
147-
}}
148-
className={cn(
149-
'flex items-center gap-1 rounded px-2 py-1 text-xs',
150-
'bg-accent-primary/20 text-accent-primary hover:bg-accent-primary/30',
151-
'transition-colors shrink-0'
152-
)}
153-
title="Add to Library"
154-
>
155-
<PlusIcon size={14} />
156-
<span className="hidden sm:inline">Add</span>
157-
</button>
158-
159-
{/* Name */}
160-
<div className="min-w-0 flex-1">
161-
<div className="flex items-center gap-2">
162-
<span className="truncate text-sm text-text-primary">
163-
{result.name}
164-
</span>
165-
{result.content_type ? (
166-
<span className={cn(
167-
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium uppercase',
168-
getCategoryColor(result.content_type)
169-
)}>
170-
{formatContentType(result.content_type)}
140+
{/* Top row: Add button + Name */}
141+
<div className="flex items-center gap-3">
142+
<button
143+
type="button"
144+
onClick={(e) => {
145+
e.preventDefault();
146+
e.stopPropagation();
147+
onAddToLibrary(result);
148+
}}
149+
className={cn(
150+
'flex items-center gap-1 rounded px-2 py-1 text-xs',
151+
'bg-accent-primary/20 text-accent-primary hover:bg-accent-primary/30',
152+
'transition-colors shrink-0'
153+
)}
154+
title="Add to Library"
155+
>
156+
<PlusIcon size={14} />
157+
<span className="hidden sm:inline">Add</span>
158+
</button>
159+
160+
<div className="min-w-0 flex-1">
161+
<div className="flex items-center gap-2">
162+
<span className="truncate text-sm text-text-primary">
163+
{result.name}
171164
</span>
172-
) : null}
165+
{result.content_type ? (
166+
<span className={cn(
167+
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium uppercase',
168+
getCategoryColor(result.content_type)
169+
)}>
170+
{formatContentType(result.content_type)}
171+
</span>
172+
) : null}
173+
</div>
173174
</div>
174175
</div>
175176

176-
{/* Stats */}
177-
<div className="hidden sm:flex items-center gap-4 text-xs text-text-muted shrink-0">
178-
<span className="w-16 text-right">{formatBytes(result.size)}</span>
177+
{/* Stats row — wraps naturally on small screens */}
178+
<div className="mt-1 ml-[52px] flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-text-muted">
179+
<span>{formatBytes(result.size)}</span>
179180
{result.files_count > 0 && (
180-
<span className="w-12 text-right">{result.files_count} files</span>
181+
<span>{result.files_count} files</span>
181182
)}
182183
<span className={cn(
183-
'w-16 text-right',
184184
result.seeders > 10 ? 'text-green-400' :
185185
result.seeders > 0 ? 'text-yellow-400' : 'text-red-400'
186186
)}>
187187
{result.seeders} S
188188
</span>
189-
<span className="w-12 text-right text-text-muted">
190-
{result.leechers} L
191-
</span>
192-
<span className="w-20 text-right hidden sm:block">
193-
{formatDate(result.created_at)}
194-
</span>
189+
<span>{result.leechers} L</span>
190+
<span>{formatDate(result.created_at)}</span>
195191
</div>
196192
</Link>
197193
))}

src/app/search/page.tsx

Lines changed: 78 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ const SearchResultsList = memo(function SearchResultsList({
141141
}
142142

143143
return (
144-
<div className="space-y-1 overflow-x-hidden">
144+
<div className="space-y-1">
145145
{results.map((result) => {
146146
const imageUrl = result.torrent_poster_url ?? (result as any).poster_url ?? result.torrent_cover_url;
147147
const displayName = result.torrent_clean_title ?? result.torrent_name;
@@ -150,98 +150,97 @@ const SearchResultsList = memo(function SearchResultsList({
150150
// Common content for both link and button versions
151151
const content = (
152152
<>
153-
{/* Add to Library button for DHT results - positioned first */}
154-
{isDht ? <button
155-
type="button"
156-
onClick={(e) => {
157-
e.preventDefault();
158-
e.stopPropagation();
159-
onAddToLibrary(result);
160-
}}
161-
className={cn(
162-
'flex items-center gap-1 rounded px-2 py-1 text-xs',
163-
'bg-accent-primary/20 text-accent-primary hover:bg-accent-primary/30',
164-
'transition-colors shrink-0'
153+
{/* Top row: buttons + thumbnail + name */}
154+
<div className="flex items-center gap-3">
155+
{/* Add to Library button for DHT results */}
156+
{isDht ? <button
157+
type="button"
158+
onClick={(e) => {
159+
e.preventDefault();
160+
e.stopPropagation();
161+
onAddToLibrary(result);
162+
}}
163+
className={cn(
164+
'flex items-center gap-1 rounded px-2 py-1 text-xs',
165+
'bg-accent-primary/20 text-accent-primary hover:bg-accent-primary/30',
166+
'transition-colors shrink-0'
167+
)}
168+
title="Add to Library"
169+
>
170+
<PlusIcon size={14} />
171+
<span className="hidden sm:inline">Add</span>
172+
</button> : null}
173+
174+
{/* Thumbnail */}
175+
<div className="relative h-10 w-7 shrink-0 overflow-hidden rounded bg-bg-tertiary">
176+
{imageUrl ? (
177+
<Image
178+
src={imageUrl}
179+
alt={displayName}
180+
fill
181+
sizes="28px"
182+
className="object-cover"
183+
unoptimized
184+
/>
185+
) : (
186+
<MediaPlaceholder alt={displayName} contentType="video" size="sm" className="h-full w-full" />
165187
)}
166-
title="Add to Library"
167-
>
168-
<PlusIcon size={14} />
169-
<span className="hidden sm:inline">Add</span>
170-
</button> : null}
171-
172-
{/* Thumbnail */}
173-
<div className="relative h-10 w-7 shrink-0 overflow-hidden rounded bg-bg-tertiary">
174-
{imageUrl ? (
175-
<Image
176-
src={imageUrl}
177-
alt={displayName}
178-
fill
179-
sizes="28px"
180-
className="object-cover"
181-
unoptimized
182-
/>
183-
) : (
184-
<MediaPlaceholder alt={displayName} contentType="video" size="sm" className="h-full w-full" />
185-
)}
186-
</div>
188+
</div>
187189

188-
{/* Name - takes most space */}
189-
<div className="min-w-0 flex-1">
190-
<div className="flex items-center gap-2">
191-
<span className="truncate text-sm text-text-primary">
192-
{displayName}
193-
</span>
194-
{/* Source badge */}
195-
{result.source ? <span
196-
className={cn(
197-
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium uppercase',
198-
result.source === 'dht'
199-
? 'bg-purple-500/20 text-purple-400'
200-
: 'bg-green-500/20 text-green-400'
201-
)}
202-
>
203-
{result.source === 'dht' ? 'DHT' : 'Library'}
190+
{/* Name */}
191+
<div className="min-w-0 flex-1">
192+
<div className="flex items-center gap-2">
193+
<span className="truncate text-sm text-text-primary">
194+
{displayName}
195+
</span>
196+
{result.source ? <span
197+
className={cn(
198+
'shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium uppercase',
199+
result.source === 'dht'
200+
? 'bg-purple-500/20 text-purple-400'
201+
: 'bg-green-500/20 text-green-400'
202+
)}
203+
>
204+
{result.source === 'dht' ? 'DHT' : 'Library'}
205+
</span> : null}
206+
{(result as any).imdb_rating ? <a
207+
href={`https://www.imdb.com/title/${(result as any).imdb_id}/`}
208+
target="_blank"
209+
rel="noopener noreferrer"
210+
className="shrink-0 text-xs text-yellow-400"
211+
onClick={(e) => e.stopPropagation()}
212+
title={`${(result as any).imdb_votes?.toLocaleString()} votes`}
213+
>
214+
{(result as any).imdb_rating}
215+
</a> : null}
216+
{(result as any).year ? <span className="shrink-0 text-[10px] text-text-muted">{(result as any).year}</span> : null}
217+
{(result as any).genres ? <span className="shrink-0 truncate text-[10px] text-text-muted max-w-[120px]">{(result as any).genres}</span> : null}
218+
</div>
219+
{result.torrent_clean_title && result.torrent_clean_title !== result.torrent_name ? <span className="block truncate text-xs text-text-muted" title={result.torrent_name}>
220+
{result.torrent_name}
204221
</span> : null}
205-
{(result as any).imdb_rating ? <a
206-
href={`https://www.imdb.com/title/${(result as any).imdb_id}/`}
207-
target="_blank"
208-
rel="noopener noreferrer"
209-
className="shrink-0 text-xs text-yellow-400"
210-
onClick={(e) => e.stopPropagation()}
211-
title={`${(result as any).imdb_votes?.toLocaleString()} votes`}
212-
>
213-
{(result as any).imdb_rating}
214-
</a> : null}
215-
{(result as any).year ? <span className="shrink-0 text-[10px] text-text-muted">{(result as any).year}</span> : null}
216-
{(result as any).genres ? <span className="shrink-0 truncate text-[10px] text-text-muted max-w-[120px]">{(result as any).genres}</span> : null}
217222
</div>
218-
{/* Show raw name if different from clean title */}
219-
{result.torrent_clean_title && result.torrent_clean_title !== result.torrent_name ? <span className="block truncate text-xs text-text-muted" title={result.torrent_name}>
220-
{result.torrent_name}
221-
</span> : null}
222223
</div>
223224

224-
{/* Stats - compact, hidden on very small screens */}
225-
<div className="hidden sm:flex items-center gap-4 text-xs text-text-muted shrink-0">
226-
<span className="w-16 text-right">{formatBytes(result.torrent_total_size)}</span>
227-
<span className="w-12 text-right">{result.torrent_file_count} files</span>
225+
{/* Stats row — wraps naturally on small screens */}
226+
<div className={cn(
227+
'mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-text-muted',
228+
isDht ? 'ml-[80px]' : 'ml-[40px]'
229+
)}>
230+
<span>{formatBytes(result.torrent_total_size)}</span>
231+
<span>{result.torrent_file_count} files</span>
228232
{result.torrent_seeders !== null && (
229233
<span className={cn(
230-
'w-16 text-right',
231234
result.torrent_seeders > 10 ? 'text-green-400' :
232235
result.torrent_seeders > 0 ? 'text-yellow-400' : 'text-red-400'
233236
)}>
234237
{result.torrent_seeders} S
235238
</span>
236239
)}
237240
{result.torrent_leechers !== null && (
238-
<span className="w-12 text-right text-text-muted">
239-
{result.torrent_leechers} L
240-
</span>
241+
<span>{result.torrent_leechers} L</span>
241242
)}
242-
<span className="w-20 text-right hidden sm:block">
243-
{formatDate(result.torrent_created_at)}
244-
</span>
243+
<span>{formatDate(result.torrent_created_at)}</span>
245244
</div>
246245
</>
247246
);
@@ -253,7 +252,7 @@ const SearchResultsList = memo(function SearchResultsList({
253252
key={result.torrent_id}
254253
href={`/dht/${result.torrent_infohash}`}
255254
className={cn(
256-
'flex items-center gap-3 rounded border border-transparent px-3 py-2',
255+
'block rounded border border-transparent px-3 py-2',
257256
'hover:border-accent-primary/30 hover:bg-bg-hover',
258257
'transition-colors'
259258
)}
@@ -268,7 +267,7 @@ const SearchResultsList = memo(function SearchResultsList({
268267
key={result.torrent_id}
269268
href={`/torrents/${result.torrent_id}`}
270269
className={cn(
271-
'flex items-center gap-3 rounded border border-transparent px-3 py-2',
270+
'block rounded border border-transparent px-3 py-2',
272271
'hover:border-accent-primary/30 hover:bg-bg-hover',
273272
'transition-colors'
274273
)}

0 commit comments

Comments
 (0)