Skip to content

Commit 740a1d1

Browse files
committed
Mobile & Repsonsive fixes
1 parent d3ae452 commit 740a1d1

8 files changed

Lines changed: 107 additions & 84 deletions

File tree

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
66
<meta name="description" content="refhub.io - Modern reference manager for researchers. Organize your papers, add tags, export BibTeX." />
77
<meta name="theme-color" content="#0f0f10" />
88
<title>refhub.io | Your Research, Organized</title>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Menu } from 'lucide-react';
2+
3+
interface MobileMenuButtonProps {
4+
onClick: () => void;
5+
className?: string;
6+
}
7+
8+
export function MobileMenuButton({ onClick, className = '' }: MobileMenuButtonProps) {
9+
return (
10+
<button
11+
className={`lg:hidden p-2 text-foreground/80 hover:text-foreground transition-colors ${className}`}
12+
onClick={onClick}
13+
aria-label="Open menu"
14+
>
15+
<Menu className="w-6 h-6" />
16+
</button>
17+
);
18+
}

src/components/publications/PublicationList.tsx

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MobileMenuButton } from '@/components/layout/MobileMenuButton';
12
import { useState, useEffect, useRef } from 'react';
23
import { Publication, Tag, Vault } from '@/types/database';
34
import { PublicationCard } from './PublicationCard';
@@ -12,15 +13,15 @@ import {
1213
Plus,
1314
Search,
1415
Download,
15-
Menu,
1616
SortAsc,
1717
CheckSquare,
1818
Square,
1919
Sparkles,
2020
Command,
2121
Upload,
2222
Network,
23-
Settings
23+
Settings,
24+
MoreVertical
2425
} from 'lucide-react';
2526
import {
2627
DropdownMenu,
@@ -140,50 +141,33 @@ export function PublicationList({
140141
return (
141142
<div className="flex-1 flex flex-col min-h-0">
142143
{/* Header */}
143-
<header className="bg-card/50 backdrop-blur-xl border-b-2 border-border px-4 lg:px-8 py-5 shrink-0 sticky top-0 z-10">
144-
<div className="flex items-center gap-4">
145-
<Button
146-
variant="ghost"
147-
size="icon"
148-
className="lg:hidden shrink-0"
144+
<header className="bg-card/50 backdrop-blur-xl border-b-2 border-border px-4 lg:px-8 py-4 shrink-0 sticky top-0 z-10">
145+
<div className="flex items-center gap-3">
146+
<MobileMenuButton
149147
onClick={onMobileMenuOpen}
150-
>
151-
<Menu className="w-5 h-5" />
152-
</Button>
148+
className="shrink-0"
149+
/>
153150

154151
<div className="flex-1 min-w-0">
155-
<div className="flex items-center gap-3">
152+
<div className="flex items-center gap-2">
156153
{selectedVault && (
157154
<div
158155
className="w-4 h-4 rounded-md shrink-0 shadow-sm"
159156
style={{ backgroundColor: selectedVault.color }}
160157
/>
161158
)}
162-
<h1 className="text-2xl lg:text-3xl font-bold truncate font-mono">
159+
<h1 className="text-lg sm:text-xl lg:text-2xl font-bold truncate font-mono leading-none">
163160
{selectedVault ? selectedVault.name : (
164161
<>
165162
<span className="text-gradient">all_papers</span>
166163
</>
167164
)}
168165
</h1>
169166
{selectedVault && (
170-
<>
171-
<QRCodeDialog vault={selectedVault} onVaultUpdate={onVaultUpdate} />
172-
{onEditVault && (
173-
<Button
174-
variant="ghost"
175-
size="icon"
176-
className="h-8 w-8 text-muted-foreground hover:text-primary shrink-0"
177-
onClick={() => onEditVault(selectedVault)}
178-
title="Edit vault settings"
179-
>
180-
<Settings className="w-4 h-4" />
181-
</Button>
182-
)}
183-
</>
167+
<QRCodeDialog vault={selectedVault} onVaultUpdate={onVaultUpdate} />
184168
)}
185169
</div>
186-
<p className="text-sm text-muted-foreground mt-1 font-mono">
170+
<p className="text-xs text-muted-foreground mt-1 font-mono truncate leading-none">
187171
{filteredPublications.length} item{filteredPublications.length !== 1 ? 's' : ''}
188172
{filters.length > 0 && (
189173
<span className="text-primary">{filters.length} filter{filters.length !== 1 ? 's' : ''}</span>
@@ -194,21 +178,39 @@ export function PublicationList({
194178
</p>
195179
</div>
196180

197-
<NotificationDropdown />
198-
199-
<Button onClick={onOpenGraph} variant="outline" size="icon" className="shrink-0" title="View relationship graph">
200-
<Network className="w-4 h-4" />
201-
</Button>
181+
<div className="flex items-center gap-2 shrink-0">
182+
<NotificationDropdown />
202183

203-
<Button onClick={onImportPublications} variant="outline" className="shrink-0 font-mono">
204-
<Upload className="w-4 h-4 lg:mr-2" />
205-
<span className="hidden lg:inline">import</span>
206-
</Button>
184+
{/* Actions Dropdown - Groups Settings, Network Graph, and Import */}
185+
<DropdownMenu>
186+
<DropdownMenuTrigger asChild>
187+
<Button variant="outline" size="icon" className="h-9 w-9" title="More actions">
188+
<MoreVertical className="w-4 h-4" />
189+
</Button>
190+
</DropdownMenuTrigger>
191+
<DropdownMenuContent align="end" className="font-mono">
192+
<DropdownMenuItem onClick={onOpenGraph}>
193+
<Network className="w-4 h-4 mr-2" />
194+
relationship_graph
195+
</DropdownMenuItem>
196+
<DropdownMenuItem onClick={onImportPublications}>
197+
<Upload className="w-4 h-4 mr-2" />
198+
import_bibtex
199+
</DropdownMenuItem>
200+
{selectedVault && onEditVault && (
201+
<DropdownMenuItem onClick={() => onEditVault(selectedVault)}>
202+
<Settings className="w-4 h-4 mr-2" />
203+
vault_settings
204+
</DropdownMenuItem>
205+
)}
206+
</DropdownMenuContent>
207+
</DropdownMenu>
207208

208-
<Button onClick={onAddPublication} variant="glow" className="shrink-0 font-mono">
209-
<Plus className="w-4 h-4 lg:mr-2" />
210-
<span className="hidden lg:inline">add_paper</span>
211-
</Button>
209+
<Button onClick={onAddPublication} variant="glow" className="h-9 font-mono">
210+
<Plus className="w-4 h-4 sm:mr-2" />
211+
<span className="hidden sm:inline">add_paper</span>
212+
</Button>
213+
</div>
212214
</div>
213215

214216
{/* Search, filters and view settings */}

src/components/ui/badge.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ const badgeVariants = cva(
2525

2626
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
2727

28-
function Badge({ className, variant, ...props }: BadgeProps) {
29-
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
30-
}
28+
const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
29+
({ className, variant, ...props }, ref) => {
30+
return <div ref={ref} className={cn(badgeVariants({ variant }), className)} {...props} />;
31+
}
32+
);
33+
Badge.displayName = "Badge";
3134

3235
export { Badge, badgeVariants };

src/components/vaults/QRCodeDialog.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,16 @@ export function QRCodeDialog({ vault, onVaultUpdate }: QRCodeDialogProps) {
132132
</Button>
133133
</DialogTrigger>
134134
{canShare && (
135-
<DialogContent className="w-[95vw] max-w-sm">
135+
<DialogContent className="sm:max-w-sm">
136136
<DialogHeader>
137137
<DialogTitle className="text-center font-mono">
138138
share "{vault.name}"
139139
</DialogTitle>
140140
</DialogHeader>
141-
<div className="flex flex-col items-center gap-6 py-4">
141+
<div className="flex flex-col items-center gap-4 sm:gap-6 py-2 sm:py-4">
142142
{/* QR Code with gradient effect */}
143-
<div className="p-6 bg-gradient-to-br from-background via-background/95 to-sidebar-accent rounded-2xl shadow-xl border-2 border-border/50 glow-purple">
144-
<div className="p-4 bg-white rounded-xl relative">
143+
<div className="p-4 sm:p-6 bg-gradient-to-br from-background via-background/95 to-sidebar-accent rounded-2xl shadow-xl border-2 border-border/50 glow-purple">
144+
<div className="p-3 sm:p-4 bg-white rounded-xl relative">
145145
<div
146146
ref={qrRef}
147147
className="relative"
@@ -151,7 +151,7 @@ export function QRCodeDialog({ vault, onVaultUpdate }: QRCodeDialogProps) {
151151
>
152152
<QRCodeCanvas
153153
value={shareUrl}
154-
size={200}
154+
size={window.innerWidth < 640 ? 180 : 200}
155155
level="H"
156156
marginSize={2}
157157
bgColor="#ffffff"
@@ -180,22 +180,24 @@ export function QRCodeDialog({ vault, onVaultUpdate }: QRCodeDialogProps) {
180180
</div>
181181
</div>
182182

183-
<div className="flex gap-3 w-full">
183+
<div className="flex gap-2 sm:gap-3 w-full">
184184
<Button
185185
variant="outline"
186186
onClick={copyShareUrl}
187-
className="flex-1 gap-2 font-mono"
187+
className="flex-1 gap-1.5 sm:gap-2 font-mono text-xs sm:text-sm"
188188
>
189-
{copied ? <Check className="w-4 h-4" /> : <Copy className="w-4 h-4" />}
190-
copy_link
189+
{copied ? <Check className="w-3.5 h-3.5 sm:w-4 sm:h-4" /> : <Copy className="w-3.5 h-3.5 sm:w-4 sm:h-4" />}
190+
<span className="hidden xs:inline">copy_link</span>
191+
<span className="xs:hidden">copy</span>
191192
</Button>
192193
<Button
193194
variant="glow"
194195
onClick={downloadQR}
195-
className="flex-1 gap-2 font-mono"
196+
className="flex-1 gap-1.5 sm:gap-2 font-mono text-xs sm:text-sm"
196197
>
197-
<Download className="w-4 h-4" />
198-
download
198+
<Download className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
199+
<span className="hidden xs:inline">download</span>
200+
<span className="xs:hidden">save</span>
199201
</Button>
200202
</div>
201203
</div>

src/pages/PublicVault.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,14 @@ export default function PublicVault() {
256256

257257
{/* Vault Header */}
258258
<div className="border-b-2 border-border bg-gradient-to-b from-card/80 to-background">
259-
<div className="max-w-6xl mx-auto px-4 py-12">
260-
<div className="flex items-start gap-4">
259+
<div className="max-w-6xl mx-auto px-4 py-8 sm:py-12">
260+
<div className="flex flex-col sm:flex-row sm:items-start gap-4">
261261
<div
262-
className="w-16 h-16 rounded-2xl shrink-0 shadow-lg"
262+
className="w-12 h-12 sm:w-16 sm:h-16 rounded-2xl shrink-0 shadow-lg"
263263
style={{ backgroundColor: vault?.color }}
264264
/>
265265
<div className="flex-1 min-w-0">
266-
<h1 className="text-3xl md:text-4xl font-bold mb-2">{vault?.name}</h1>
266+
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold mb-2">{vault?.name}</h1>
267267
{vault?.description && (
268268
<p className="text-muted-foreground font-mono text-sm mb-4">
269269
// {vault.description}
@@ -278,7 +278,7 @@ export default function PublicVault() {
278278
</div>
279279

280280
{/* Fork/Favorite buttons - visible to all users */}
281-
<div className="flex gap-2 shrink-0">
281+
<div className="flex gap-2 shrink-0 w-full sm:w-auto">
282282
<Button
283283
variant="outline"
284284
size="sm"
@@ -287,8 +287,8 @@ export default function PublicVault() {
287287
className={`font-mono ${vault && isFavorite(vault.id) ? 'text-rose-500 border-rose-500/30' : ''}`}
288288
title={isOwner ? 'you_own_this_vault' : undefined}
289289
>
290-
<Heart className={`w-4 h-4 mr-1.5 ${vault && isFavorite(vault.id) ? 'fill-rose-500' : ''}`} />
291-
{vault && isFavorite(vault.id) ? 'favorited' : 'favorite'}
290+
<Heart className={`w-4 h-4 sm:mr-1.5 ${vault && isFavorite(vault.id) ? 'fill-rose-500' : ''}`} />
291+
<span className="hidden sm:inline">{vault && isFavorite(vault.id) ? 'favorited' : 'favorite'}</span>
292292
</Button>
293293
<Button
294294
variant="outline"
@@ -298,8 +298,8 @@ export default function PublicVault() {
298298
title={isOwner ? 'you_own_this_vault' : undefined}
299299
className="font-mono"
300300
>
301-
<GitFork className="w-4 h-4 mr-1.5" />
302-
{forking ? 'forking...' : 'fork'}
301+
<GitFork className="w-4 h-4 sm:mr-1.5" />
302+
<span className="hidden sm:inline">{forking ? 'forking...' : 'fork'}</span>
303303
</Button>
304304
</div>
305305
</div>

src/pages/SharedVault.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,14 @@ export default function SharedVault() {
322322

323323
{/* Vault Header */}
324324
<div className="border-b-2 border-border bg-gradient-to-b from-card/80 to-background">
325-
<div className="max-w-6xl mx-auto px-4 py-12">
326-
<div className="flex items-start gap-4">
325+
<div className="max-w-6xl mx-auto px-4 py-8 sm:py-12">
326+
<div className="flex flex-col sm:flex-row sm:items-start gap-4">
327327
<div
328-
className="w-16 h-16 rounded-2xl shrink-0 shadow-lg"
328+
className="w-12 h-12 sm:w-16 sm:h-16 rounded-2xl shrink-0 shadow-lg"
329329
style={{ backgroundColor: vault?.color }}
330330
/>
331331
<div className="flex-1 min-w-0">
332-
<h1 className="text-3xl md:text-4xl font-bold mb-2">{vault?.name}</h1>
332+
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold mb-2">{vault?.name}</h1>
333333
{vault?.description && (
334334
<p className="text-muted-foreground font-mono text-sm mb-4">
335335
// {vault.description}
@@ -344,7 +344,7 @@ export default function SharedVault() {
344344
</div>
345345

346346
{/* Fork/Favorite buttons */}
347-
<div className="flex gap-2 shrink-0">
347+
<div className="flex gap-2 shrink-0 w-full sm:w-auto">
348348
{user && (
349349
<>
350350
<Button
@@ -356,9 +356,9 @@ export default function SharedVault() {
356356
title={isOwner ? 'you_own_this_vault' : undefined}
357357
>
358358
<Heart
359-
className={`w-4 h-4 mr-1.5 ${vault && isFavorite(vault.id) ? 'fill-rose-500' : ''}`}
359+
className={`w-4 h-4 sm:mr-1.5 ${vault && isFavorite(vault.id) ? 'fill-rose-500' : ''}`}
360360
/>
361-
{vault && isFavorite(vault.id) ? 'favorited' : 'favorite'}
361+
<span className="hidden sm:inline">{vault && isFavorite(vault.id) ? 'favorited' : 'favorite'}</span>
362362
</Button>
363363
{!isOwner && (
364364
<Button
@@ -368,8 +368,8 @@ export default function SharedVault() {
368368
disabled={forking}
369369
className="font-mono"
370370
>
371-
<GitFork className="w-4 h-4 mr-1.5" />
372-
{forking ? 'forking...' : 'fork'}
371+
<GitFork className="w-4 h-4 sm:mr-1.5" />
372+
<span className="hidden sm:inline">{forking ? 'forking...' : 'fork'}</span>
373373
</Button>
374374
)}
375375
</>
@@ -381,7 +381,8 @@ export default function SharedVault() {
381381
size="sm"
382382
className="font-mono"
383383
>
384-
sign_in_to_interact
384+
<span className="hidden xs:inline">sign_in_to_interact</span>
385+
<span className="xs:hidden">sign_in</span>
385386
</Button>
386387
)}
387388
</div>

src/pages/TheCodex.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MobileMenuButton } from '@/components/layout/MobileMenuButton';
12
import { useState, useEffect } from 'react';
23
import { Link, useNavigate } from 'react-router-dom';
34
import { supabase } from '@/integrations/supabase/client';
@@ -275,15 +276,11 @@ export default function TheCodex() {
275276
<div className={`flex-1 ${user ? 'lg:pl-72' : ''}`}>
276277
<div className="min-h-screen flex flex-col">
277278
{/* Mobile menu button - fixed position */}
278-
{user && (
279-
<Button
280-
variant="ghost"
281-
size="icon"
282-
className="lg:hidden fixed top-4 left-4 z-50 bg-card/80 backdrop-blur-sm border-2 border-border shadow-lg"
279+
{user && !isMobileSidebarOpen && (
280+
<MobileMenuButton
283281
onClick={() => setIsMobileSidebarOpen(true)}
284-
>
285-
<Menu className="w-5 h-5" />
286-
</Button>
282+
className="fixed top-4 left-4 z-50"
283+
/>
287284
)}
288285
{/* Hero */}
289286
<div className="w-full border-b-2 border-border bg-gradient-to-b from-amber-500/5 via-orange-500/5 to-background">

0 commit comments

Comments
 (0)