Skip to content

Commit 68a2c63

Browse files
commrelayunitC-3POvelitchkoclaude
authored
fix: polish mobile publication layouts (#106)
* fix: polish mobile publication layouts * fix(mobile): dialog-mobile now truly fullscreen height (100dvh, no insets) * fix(mobile): remove rounded corners and add max-w-[100vw] on all dialog-mobile dialogs Remove rounded-2xl from mobile fullscreen dialogs to ensure sharp edges, add max-w-[100vw] for true full-width on wider phones, and shift rounded corners to sm: breakpoint for desktop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(mobile): keyboard shortcuts overlay now fullscreen and scrollable on mobile * fix(mobile): vault detail header non-sticky on mobile, prevents overlap with publication list header * fix(mobile): reduce ASCII art font size to prevent clipping on narrow screens * fix(mobile): toolbar controls now wrap horizontally instead of stacking vertically * fix(mobile): consistent dialog headings — // prefix, uniform font size, left-aligned on all viewports * fix: add // prefix to account_settings page heading --------- Co-authored-by: C-3PO <c3po.bot@gmail.com> Co-authored-by: velitchko <velitchkofilipov@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7951182 commit 68a2c63

23 files changed

Lines changed: 81 additions & 101 deletions

src/components/layout/BugReportButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function BugReportButton() {
2121
};
2222

2323
return (
24-
<div className="pointer-events-none fixed bottom-4 right-4 z-40 sm:bottom-6 sm:right-6">
24+
<div className="pointer-events-none fixed bottom-[calc(1rem+env(safe-area-inset-bottom))] right-4 z-40 sm:bottom-6 sm:right-6">
2525
<div className="flex flex-col items-end gap-2 pointer-events-auto">
2626
<Badge
2727
variant="outline"

src/components/layout/ScrollToTopButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function ScrollToTopButton() {
2727
};
2828

2929
return (
30-
<div className="pointer-events-none fixed bottom-[calc(1rem+4.75rem)] right-4 z-40 sm:bottom-[calc(1.5rem+4.75rem)] sm:right-6">
30+
<div className="pointer-events-none fixed bottom-[calc(1rem+4.75rem+env(safe-area-inset-bottom))] right-4 z-40 sm:bottom-[calc(1.5rem+4.75rem)] sm:right-6">
3131
<Button
3232
onClick={handleScrollToTop}
3333
size="icon"

src/components/profile/ProfileDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@ export function ProfileDialog({ open, onOpenChange }: ProfileDialogProps) {
282282
description="You have unsaved changes to your profile. Would you like to save them before closing?"
283283
/>
284284
<Dialog open={open} onOpenChange={handleDialogClose}>
285-
<DialogContent className="dialog-mobile rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-3xl sm:max-h-[90vh] border-2 bg-card/95 backdrop-blur-xl overflow-hidden flex flex-col gap-0 p-0">
285+
<DialogContent className="dialog-mobile max-w-[100vw] sm:rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-3xl sm:max-h-[90vh] border-2 bg-card/95 backdrop-blur-xl overflow-hidden flex flex-col gap-0 p-0">
286286
<DialogHeader className="px-6 pt-6 pb-4">
287-
<DialogTitle className="text-2xl font-bold font-mono">edit_profile</DialogTitle>
287+
<DialogTitle className="text-xl sm:text-2xl font-bold font-mono">// edit_profile</DialogTitle>
288288
</DialogHeader>
289289

290290
<Form {...form}>

src/components/publications/AddImportDialog.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ export function AddImportDialog({
308308

309309
return (
310310
<Dialog open={open} onOpenChange={onOpenChange}>
311-
<DialogContent forceMount className="dialog-mobile rounded-2xl p-0 border-2 bg-card/95 backdrop-blur-xl overflow-hidden flex flex-col gap-0 min-h-0 sm:h-auto sm:w-[95vw] sm:max-w-4xl sm:max-h-[90vh] data-[state=closed]:hidden">
311+
<DialogContent forceMount className="dialog-mobile max-w-[100vw] p-0 border-2 bg-card/95 backdrop-blur-xl overflow-hidden flex flex-col gap-0 min-h-0 sm:rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-4xl sm:max-h-[90vh] data-[state=closed]:hidden">
312312
<DialogHeader className="p-4 sm:p-6 pb-0">
313313
<DialogTitle className="text-xl sm:text-2xl font-bold font-mono">
314314
// add_<span className="text-gradient">papers</span>
@@ -422,7 +422,7 @@ export function AddImportDialog({
422422
placeholder="Author 1, Author 2, ..." className="font-mono text-sm" />
423423
</div>
424424
{/* Year + Type */}
425-
<div className="grid grid-cols-2 gap-4">
425+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
426426
<div className="space-y-2">
427427
<Label className="font-semibold font-mono">year</Label>
428428
<Input type="number" value={manualForm.year ?? ''} onChange={(e) => setManualForm(f => ({ ...f, year: e.target.value ? parseInt(e.target.value) : null }))}
@@ -445,7 +445,7 @@ export function AddImportDialog({
445445
placeholder="Journal name" className="font-mono text-sm" />
446446
</div>
447447
{/* Volume / Issue / Pages */}
448-
<div className="grid grid-cols-3 gap-4">
448+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
449449
<div className="space-y-2">
450450
<Label className="font-semibold font-mono">volume</Label>
451451
<Input value={manualForm.volume || ''} onChange={(e) => setManualForm(f => ({ ...f, volume: e.target.value }))}
@@ -463,7 +463,7 @@ export function AddImportDialog({
463463
</div>
464464
</div>
465465
{/* DOI + URL */}
466-
<div className="grid grid-cols-2 gap-4">
466+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
467467
<div className="space-y-2">
468468
<Label className="font-semibold font-mono">doi</Label>
469469
<Input value={manualForm.doi || ''} onChange={(e) => setManualForm(f => ({ ...f, doi: e.target.value }))}
@@ -614,7 +614,7 @@ export function AddImportDialog({
614614

615615
{/* ISSN + EID (articles) */}
616616
{manualForm.publication_type === 'article' && (
617-
<div className="grid grid-cols-2 gap-4">
617+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
618618
<div className="space-y-2">
619619
<Label className="font-semibold font-mono">issn</Label>
620620
<Input value={manualForm.issn || ''} onChange={(e) => setManualForm(f => ({ ...f, issn: e.target.value }))}

src/components/publications/ExportDialog.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,10 @@ export function ExportDialog({
160160

161161
return (
162162
<Dialog open={open} onOpenChange={onOpenChange}>
163-
<DialogContent className="dialog-mobile rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-lg sm:max-h-[90vh] flex flex-col overflow-hidden border-2 bg-card/95 backdrop-blur-xl p-0">
163+
<DialogContent className="dialog-mobile max-w-[100vw] sm:rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-lg sm:max-h-[90vh] flex flex-col overflow-hidden border-2 bg-card/95 backdrop-blur-xl p-0">
164164
<DialogHeader className="px-4 sm:px-6 pt-4 sm:pt-6 pb-4">
165-
<DialogTitle className="flex items-center gap-2 font-mono text-lg sm:text-xl">
166-
<FileText className="w-5 h-5 text-primary" />
167-
export_references
165+
<DialogTitle className="flex items-center gap-2 font-mono text-xl sm:text-2xl font-bold">
166+
// export_references
168167
<KbdHint shortcut="Ctrl+E" className="ml-auto" size="sm" />
169168
</DialogTitle>
170169
</DialogHeader>

src/components/publications/PublicationCard.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ export function PublicationCard({
110110
)}
111111
onClick={onOpen}
112112
>
113-
<CardContent className="p-5">
114-
<div className="flex items-start gap-4">
113+
<CardContent className="p-3 sm:p-5">
114+
<div className="flex items-start gap-3 sm:gap-4">
115115
<div
116116
className="pt-1"
117117
onClick={(e) => {
@@ -126,13 +126,13 @@ export function PublicationCard({
126126
</div>
127127

128128
<div className="flex-1 min-w-0">
129-
<div className="flex items-start justify-between gap-3">
129+
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
130130
<div className="flex-1 min-w-0">
131-
<h3 className="font-bold text-lg text-foreground leading-tight line-clamp-2 group-hover:text-primary transition-colors">
131+
<h3 className="font-bold text-base sm:text-lg text-foreground leading-tight line-clamp-3 sm:line-clamp-2 group-hover:text-primary transition-colors">
132132
{publication.title}
133133
</h3>
134134
{(show.authors || show.year || show.type) && (
135-
<p className="text-sm text-muted-foreground mt-1.5 font-mono">
135+
<p className="text-xs sm:text-sm text-muted-foreground mt-1.5 font-mono">
136136
{show.authors && formatAuthors(publication.authors)}
137137
{show.year && publication.year && (
138138
<span className="text-neon-green">{show.authors ? ' • ' : ''}{publication.year}</span>
@@ -155,7 +155,7 @@ export function PublicationCard({
155155
)}
156156
</div>
157157

158-
<div className="flex items-center gap-1 shrink-0">
158+
<div className="flex flex-wrap items-center gap-1 shrink-0 sm:justify-end">
159159
{show.pdf && publication.pdf_url && (
160160
<a
161161
href={publication.pdf_url}
@@ -195,7 +195,7 @@ export function PublicationCard({
195195
<Button
196196
variant="ghost"
197197
size="icon"
198-
className="shrink-0 opacity-0 group-hover:opacity-100 transition-opacity h-9 w-9"
198+
className="shrink-0 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity h-9 w-9"
199199
>
200200
<MoreVertical className="w-4 h-4" />
201201
</Button>

src/components/publications/PublicationDialog.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,11 +827,11 @@ export function PublicationDialog({
827827
className="w-screen max-w-none box-border h-screen sm:w-[95vw] sm:max-w-3xl sm:h-auto sm:max-h-[90vh] m-0 p-0 border-0 sm:border-2 bg-card/95 backdrop-blur-xl overflow-x-hidden overflow-y-auto flex flex-col"
828828
>
829829
<DialogHeader className="px-2 py-3 sm:p-6 pb-2 sm:pb-0">
830-
<DialogTitle className="text-lg sm:text-2xl font-bold font-mono pr-8 sm:pr-10">
830+
<DialogTitle className="text-xl sm:text-2xl font-bold font-mono pr-8 sm:pr-10">
831831
{publication ? (
832-
<span>edit_<span className="text-gradient">paper</span></span>
832+
<span>// edit_<span className="text-gradient">paper</span></span>
833833
) : (
834-
<span>add_<span className="text-gradient">paper</span></span>
834+
<span>// add_<span className="text-gradient">paper</span></span>
835835
)}
836836
</DialogTitle>
837837
{publication && onCheckSync && (

src/components/publications/PublicationList.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ export function PublicationList({
400400
return (
401401
<div className="flex-1 flex flex-col min-h-0 overflow-x-hidden">
402402
{/* Header */}
403-
<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">
404-
<div className="flex items-center gap-3">
403+
<header className="bg-card/50 backdrop-blur-xl border-b-2 border-border px-3 sm:px-4 lg:px-8 py-3 sm:py-4 shrink-0 sticky top-0 z-10">
404+
<div className="flex items-center gap-2 sm:gap-3">
405405
<MobileMenuButton
406406
onClick={onMobileMenuOpen}
407407
className="shrink-0"
@@ -440,7 +440,7 @@ export function PublicationList({
440440
</p>
441441
</div>
442442

443-
<div className="flex items-center gap-2 shrink-0">
443+
<div className="flex items-center gap-1 sm:gap-2 shrink-0">
444444
<NotificationDropdown />
445445

446446
{/* Visible buttons on larger screens */}
@@ -531,7 +531,7 @@ export function PublicationList({
531531
)}
532532

533533
{onAddPublication && (
534-
<Button onClick={onAddPublication} variant="glow" className="h-9 font-mono">
534+
<Button onClick={onAddPublication} variant="glow" className="h-9 w-9 sm:w-auto sm:px-3 font-mono">
535535
<Plus className="w-4 h-4 sm:mr-2" />
536536
<span className="hidden sm:inline">add_paper</span>
537537
</Button>
@@ -540,9 +540,9 @@ export function PublicationList({
540540
</div>
541541

542542
{/* Search, filters and view settings */}
543-
<div className="flex items-center gap-3 mt-5 flex-wrap">
543+
<div className="mt-4 sm:mt-5 flex flex-row flex-wrap gap-2 sm:gap-3 items-center">
544544
{/* Search input — left side, grows to fill available space */}
545-
<div className="relative flex-1 min-w-[160px]">
545+
<div className="relative w-full sm:flex-1 sm:min-w-[220px]">
546546
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
547547
<Input
548548
ref={searchInputRef}
@@ -692,7 +692,7 @@ export function PublicationList({
692692
{/* Publication list */}
693693
<div
694694
ref={listContainerRef}
695-
className="flex-1 overflow-y-auto scrollbar-thin overflow-x-hidden p-4 lg:p-8 outline-none"
695+
className="flex-1 overflow-y-auto scrollbar-thin overflow-x-hidden p-3 sm:p-4 lg:p-8 pb-[calc(1rem+env(safe-area-inset-bottom))] outline-none"
696696
{...kbNav.containerProps}
697697
>
698698
{filteredPublications.length === 0 ? (
@@ -743,7 +743,7 @@ export function PublicationList({
743743
onCheckSync={onCheckPublicationSync}
744744
/>
745745
) : (
746-
<div className="space-y-4 max-w-4xl mx-auto">
746+
<div className="space-y-3 sm:space-y-4 max-w-4xl mx-auto">
747747
{filteredPublications.map((pub, index) => (
748748
<div
749749
key={pub.id}

src/components/publications/PublicationSyncDialog.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@ export function PublicationSyncDialog({
5656
<Dialog open={open} onOpenChange={onOpenChange}>
5757
<DialogContent className="max-w-2xl bg-card border-2 backdrop-blur-xl">
5858
<DialogHeader>
59-
<DialogTitle className="font-mono flex items-center gap-2 text-base">
60-
<RefreshCw className="w-4 h-4" />
61-
semantic_scholar_sync()
59+
<DialogTitle className="font-mono text-xl sm:text-2xl font-bold">
60+
// semantic_scholar_sync()
6261
</DialogTitle>
6362
<DialogDescription className="font-mono text-xs">
6463
Review incoming metadata. Notes and tags are not affected.

src/components/publications/PublicationViewDialog.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ export function PublicationViewDialog({
6767

6868
return (
6969
<Dialog open={open} onOpenChange={onOpenChange}>
70-
<DialogContent className="publication-view-dialog w-[min(calc(100vw-2rem),48rem)] max-w-[calc(100vw-2rem)] rounded-2xl border-2 bg-card/95 backdrop-blur-xl max-h-[min(90vh,56rem)] overflow-y-auto shadow-2xl sm:max-w-3xl">
71-
<DialogHeader className="space-y-3">
70+
<DialogContent className="dialog-mobile publication-view-dialog max-w-[100vw] border-2 bg-card/95 backdrop-blur-xl overflow-hidden shadow-2xl sm:rounded-2xl sm:h-auto sm:w-[95vw] sm:max-w-3xl sm:max-h-[90vh] p-0 gap-0">
71+
<DialogHeader className="shrink-0 space-y-3 px-4 sm:px-6 pt-4 sm:pt-6 pb-4 border-b border-border/60">
7272
<div className="flex flex-wrap items-center gap-2">
7373
{publication.publication_type && (
7474
<Badge variant="outline" className="font-mono text-xs">
@@ -81,20 +81,20 @@ export function PublicationViewDialog({
8181
</Badge>
8282
)}
8383
</div>
84-
<DialogTitle className="text-xl sm:text-2xl font-bold leading-tight">
85-
{publication.title}
84+
<DialogTitle className="pr-8 text-xl sm:text-2xl font-bold font-mono leading-tight">
85+
// {publication.title}
8686
</DialogTitle>
8787
<DialogDescription className="text-sm font-mono">
8888
{publication.authors.length > 0 ? publication.authors.join(', ') : 'unknown author'}
8989
{publication.updated_at && ` • updated ${formatTimeAgo(publication.updated_at)}`}
9090
</DialogDescription>
9191
</DialogHeader>
9292

93-
<div className="space-y-6">
93+
<div className="flex-1 min-h-0 overflow-y-auto space-y-5 sm:space-y-6 px-4 sm:px-6 py-4 sm:py-6">
9494
{(publication.doi || publication.url || publication.pdf_url || driveLoading || driveUrl) && (
95-
<div className="flex flex-wrap gap-2">
95+
<div className="grid grid-cols-1 sm:flex sm:flex-wrap gap-2">
9696
{publication.doi && (
97-
<Button asChild variant="outline" size="sm" className="font-mono">
97+
<Button asChild variant="outline" size="sm" className="w-full justify-start sm:w-auto font-mono">
9898
<a
9999
href={`https://doi.org/${encodeURIComponent(publication.doi)}`}
100100
target="_blank"
@@ -106,29 +106,29 @@ export function PublicationViewDialog({
106106
</Button>
107107
)}
108108
{publication.url && (
109-
<Button asChild variant="outline" size="sm" className="font-mono">
109+
<Button asChild variant="outline" size="sm" className="w-full justify-start sm:w-auto font-mono">
110110
<a href={publication.url} target="_blank" rel="noopener noreferrer">
111111
<ExternalLink className="w-4 h-4 mr-2" />
112112
link
113113
</a>
114114
</Button>
115115
)}
116116
{publication.pdf_url && (
117-
<Button asChild variant="outline" size="sm" className="font-mono">
117+
<Button asChild variant="outline" size="sm" className="w-full justify-start sm:w-auto font-mono">
118118
<a href={publication.pdf_url} target="_blank" rel="noopener noreferrer">
119119
<FileText className="w-4 h-4 mr-2" />
120120
publisher_pdf
121121
</a>
122122
</Button>
123123
)}
124124
{driveLoading && (
125-
<Button variant="outline" size="sm" className="font-mono" disabled>
125+
<Button variant="outline" size="sm" className="w-full justify-start sm:w-auto font-mono" disabled>
126126
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
127127
drive_pdf
128128
</Button>
129129
)}
130130
{!driveLoading && driveUrl && (
131-
<Button asChild variant="outline" size="sm" className="font-mono">
131+
<Button asChild variant="outline" size="sm" className="w-full justify-start sm:w-auto font-mono">
132132
<a href={driveUrl} target="_blank" rel="noopener noreferrer">
133133
<GoogleDriveIcon className="w-4 h-4 mr-2" />
134134
drive_pdf
@@ -201,8 +201,8 @@ export function PublicationViewDialog({
201201
</div>
202202

203203
{onEdit && (
204-
<DialogFooter>
205-
<Button type="button" className="font-mono" onClick={() => onEdit(publication)}>
204+
<DialogFooter className="shrink-0 border-t border-border/60 px-4 sm:px-6 py-4 flex-col-reverse sm:flex-row gap-2">
205+
<Button type="button" className="w-full sm:w-auto font-mono" onClick={() => onEdit(publication)}>
206206
<Pencil className="w-4 h-4 mr-2" />
207207
edit
208208
</Button>

0 commit comments

Comments
 (0)