From 41c86373bb1a1546a8c8857ecfcbb6dd7cfd8c28 Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 05:51:15 +0000 Subject: [PATCH 1/7] feat(ui): overhaul UI for modern, intuitive design This major update modernizes and simplifies the entire user interface across the application for a more appealing, user-friendly experience. - Revamps the landing page, authentication, header, and library views with better layout, modern gradients, glassmorphism, improved spacing, and animation utility classes - Refactors library card grid, upload form, and empty/loader states for visual polish and feedback - Updates PDF reader controls and loading screens for consistency - Implements improved global animation and utility styles The new UI enhances usability and aesthetics with no breaking changes. --- src/app/(app)/library/page.tsx | 152 ++++++++++++++++++---------- src/app/(auth)/sign-in/page.tsx | 117 ++++++++++++++------- src/app/(auth)/sign-up/page.tsx | 88 ++++++++++------ src/app/globals.css | 102 +++++++++++++++++++ src/app/layout.tsx | 2 +- src/app/page.tsx | 105 ++++++++++++++++--- src/components/header.tsx | 63 +++++++----- src/components/reader/PdfReader.tsx | 108 ++++++++++++-------- 8 files changed, 535 insertions(+), 202 deletions(-) diff --git a/src/app/(app)/library/page.tsx b/src/app/(app)/library/page.tsx index ba1ba62..6452b46 100644 --- a/src/app/(app)/library/page.tsx +++ b/src/app/(app)/library/page.tsx @@ -147,11 +147,14 @@ export default function LibraryPage() { if (loading) { return ( -
- - -
-

{loadingMessage}

+
+ + +
+
+
+
+

{loadingMessage}

@@ -160,12 +163,24 @@ export default function LibraryPage() { if (!email) { return ( -
- - - -

Please sign in to view your library

-
@@ -175,10 +190,10 @@ export default function LibraryPage() { } return ( -
-
-

My Library

-

Manage your digital book collection

+
+
+

My Library

+

Manage and read your digital book collection

@@ -191,54 +206,69 @@ export default function LibraryPage() { function BookList({ books, onDeleteBook }: { books: BookRow[]; onDeleteBook: (id: string) => void }) { if (!books.length) { return ( - - - -

No books yet

-

Upload a PDF to get started with your digital library. EPUB support coming soon!

+ + +
+
+
+ +
+
+

Your library is empty

+

+ Upload a PDF to get started with your digital library. EPUB support coming soon! +

); } return ( -
- {books.map((b) => ( - +
+ {books.map((b, index) => ( + -
+
{b.cover_url ? ( {b.title ) : ( -
+
{b.format === 'pdf' ? ( - + ) : ( - + )}
)} + + {/* Overlay gradient on hover */} +
+ {b.format?.toUpperCase()} - {/* Delete button - always visible */} -
+ {/* Delete button */} +
@@ -264,9 +294,9 @@ function BookList({ books, onDeleteBook }: { books: BookRow[]; onDeleteBook: (id
-
- -

+
+ +

{b.title ?? "Untitled"}

@@ -319,21 +349,23 @@ function UploadForm({ onUploaded }: { onUploaded: () => void }) { }, [file, onUploaded]); return ( - - - - + + + +

+ +
Upload a Book - - Upload PDF files to add them to your library. EPUB support coming soon! + + Add PDF files to your library. EPUB support coming soon! -
-
- -
+ +
+ +
void }) { type="button" variant="outline" onClick={() => document.getElementById(fileInputId)?.click()} - className="flex items-center space-x-2 cursor-pointer" + className="flex items-center gap-2 cursor-pointer h-11 border-2 border-dashed hover:border-primary smooth-transition hover:bg-primary/5" > - Choose file + Choose file - - {file?.name ?? "No file selected"} - +
+ {file ? ( +
+ + {file.name} + +
+ ) : ( + No file selected + )} +
-
- -
- {mode === "sign-in" ? ( - - ) : ( - - )} +
+ +
+ OR
+
+ {mode === "sign-in" ? ( + + ) : ( + + )} +
+ {status && ( -
-

{status}

+
+

{status}

)} -
-
diff --git a/src/app/(auth)/sign-up/page.tsx b/src/app/(auth)/sign-up/page.tsx index 33655ed..0b0d5b2 100644 --- a/src/app/(auth)/sign-up/page.tsx +++ b/src/app/(auth)/sign-up/page.tsx @@ -34,21 +34,34 @@ export default function SignUpPage() { } return ( -
- - -
- +
+ {/* Background decoration */} +
+
+
+
+ + + +
+
+
+
+ +
+
+
+
+ Get started + + Create an account to start your reading journey +
- Create account - - Sign up to start your reading journey with BookMarked -
- -
+ +
- + setEmail(e.target.value)} placeholder="you@example.com" + className="h-11 smooth-transition focus:border-primary" />
- + setPassword(e.target.value)} placeholder="Create a password" + className="h-11 smooth-transition focus:border-primary" /> -

+

Password must be at least 6 characters and contain both letters and digits.

- -
- -
- +
+ +
+ OR
+
+ +
+ {status && ( -
-

{status}

+
+

{status}

)} -
-
diff --git a/src/app/globals.css b/src/app/globals.css index bc9b743..1949f7b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -204,3 +204,105 @@ scrollbar-width: thin; scrollbar-color: hsl(var(--muted-foreground)) hsl(var(--muted)); } + +/* Modern Animations */ +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.9); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slide-in-left { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +/* Utility classes */ +.animate-fade-in-up { + animation: fade-in-up 0.6s ease-out forwards; +} + +.animate-fade-in { + animation: fade-in 0.6s ease-out forwards; +} + +.animate-scale-in { + animation: scale-in 0.5s ease-out forwards; +} + +.animate-slide-in-left { + animation: slide-in-left 0.6s ease-out forwards; +} + +.animation-delay-200 { + animation-delay: 0.2s; +} + +.animation-delay-400 { + animation-delay: 0.4s; +} + +.animation-delay-600 { + animation-delay: 0.6s; +} + +.animation-delay-800 { + animation-delay: 0.8s; +} + +/* Glassmorphism effect */ +.glass { + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.dark .glass { + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.05); +} + +/* Smooth transitions */ +.smooth-transition { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Gradient text */ +.gradient-text { + background: linear-gradient(135deg, hsl(var(--primary)) 0%, hsl(var(--accent)) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3b4a37c..b553272 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -37,7 +37,7 @@ export default function RootLayout({
-
+
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx index 5d4d3a0..f5a5a55 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,13 +3,16 @@ import { useEffect, useState } from "react"; import { supabase } from "@/lib/supabase"; import { Button } from "@/components/ui/button"; -import { BookOpen, ArrowRight } from "lucide-react"; +import { Card, CardContent } from "@/components/ui/card"; +import { BookOpen, ArrowRight, Sparkles, Cloud, Lock, Zap } from "lucide-react"; import Link from "next/link"; export default function Home() { const [signedIn, setSignedIn] = useState(null); + const [mounted, setMounted] = useState(false); useEffect(() => { + setMounted(true); let active = true; (async () => { const { data: { user } } = await supabase.auth.getUser(); @@ -28,29 +31,43 @@ export default function Home() { return (
{/* Hero Section */} -
-
+
+ {/* Enhanced gradient background */} +
+
+
+
+
+
-
- + {/* Icon with animation */} +
+
+
+
+ +
+
-
-

- BookMarked + {/* Heading with stagger animation */} +
+

+ BookMarked

-

- Your personal digital library. Read your EPUB and PDF books anywhere. Sync your progress across all devices seamlessly. +

+ Your personal digital library. Read, organize, and sync your books across all devices.

-
-
@@ -58,6 +75,68 @@ export default function Home() {

+ {/* Features Section */} +
+
+
+ + +
+ +
+
+

Cloud Sync

+

+ Your library and reading progress synced seamlessly across all your devices. +

+
+
+
+ + + +
+ +
+
+

Beautiful Reader

+

+ Enjoy a distraction-free reading experience with customizable themes. +

+
+
+
+ + + +
+ +
+
+

Offline Ready

+

+ Read your books anytime, anywhere with full offline support via PWA. +

+
+
+
+ + + +
+ +
+
+

Private & Secure

+

+ Your books and data are encrypted and stored securely in your account. +

+
+
+
+
+
+
); } diff --git a/src/components/header.tsx b/src/components/header.tsx index 3106849..0df61d4 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -86,43 +86,60 @@ export function Header() { } return ( -
-
-
- - - BookMarked +
+
+
+ +
+
+
+ +
+
+ BookMarked - +
{!isOnline && ( - Offline + + Offline + )} {signedIn ? ( - ) : ( - )} diff --git a/src/components/reader/PdfReader.tsx b/src/components/reader/PdfReader.tsx index 4f47879..94da154 100644 --- a/src/components/reader/PdfReader.tsx +++ b/src/components/reader/PdfReader.tsx @@ -340,9 +340,17 @@ export default function PdfReader({ fileUrl, bookId }: PdfReaderProps) { if (loading) { return (
-
-
-

Loading PDF... {progress > 0 ? `${progress}%` : ''}

+
+
+
+
+
+
+

Loading PDF

+ {progress > 0 && ( +

{progress}%

+ )} +
); @@ -351,13 +359,20 @@ export default function PdfReader({ fileUrl, bookId }: PdfReaderProps) { if (error) { return (
-
-
⚠️
-

Error

-

{error}

+
+
+
+
+
⚠️
+
+
+
+

Error Loading PDF

+

{error}

+
@@ -369,25 +384,26 @@ export default function PdfReader({ fileUrl, bookId }: PdfReaderProps) { return (
{/* Top Toolbar */} -
-
+
+
- + +
-
+
= 1 && val <= numPages) setPageNum(val); }} - className="w-14 sm:w-16 px-2 py-1 text-center bg-background border border-border rounded" + className="w-12 sm:w-14 px-1 py-0.5 text-center bg-transparent border-0 focus:outline-none focus:ring-0 font-medium" min={1} max={numPages} /> - of {numPages} + / {numPages}
@@ -415,32 +431,32 @@ export default function PdfReader({ fileUrl, bookId }: PdfReaderProps) { - + {Math.round(scale * 100)}%
@@ -448,42 +464,46 @@ export default function PdfReader({ fileUrl, bookId }: PdfReaderProps) {
{/* Canvas Container */} -
-
+
+
{rendering && (
-
+
+
+
+
)}
{/* Performance Info & Keyboard Shortcuts */} -
-
-
+
+
+
{prefetchedPages.size > 0 && ( - - 📚 {prefetchedPages.size} pages cached + + 📚 + {prefetchedPages.size} cached )} {readingSpeed > 0 && ( - - ⚡ {Math.round(readingSpeed * 60)} pages/min + + + {Math.round(readingSpeed * 60)} pages/min )}
-

- Previous •{" "} - Next •{" "} - + Zoom In •{" "} - - Zoom Out •{" "} - F Fullscreen +

+ Prev •{" "} + Next •{" "} + + Zoom •{" "} + F Fullscreen

From 120b867006f01f4879fb8e587b7e1fd0dfcb3297 Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 05:59:16 +0000 Subject: [PATCH 2/7] feat(theme): overhaul color palette and responsiveness Adopted a warm and cozy color system with modern gradients and glass effects. Improved page responsiveness, modernized visual hierarchy, and enhanced layout spacing. Added new utility classes for cards, glows, and more expressive focus/hover states. --- src/app/globals.css | 308 ++++++++++++++++++++++++++------------ src/app/layout.tsx | 2 +- src/app/page.tsx | 123 ++++++++------- src/components/header.tsx | 56 ++++--- 4 files changed, 314 insertions(+), 175 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 1949f7b..5db2f0d 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -57,111 +57,141 @@ } :root { - --background: oklch(0.9777 0.0041 301.4256); - --foreground: oklch(0.3651 0.0325 287.0807); - --card: oklch(1.0000 0 0); - --card-foreground: oklch(0.3651 0.0325 287.0807); - --popover: oklch(1.0000 0 0); - --popover-foreground: oklch(0.3651 0.0325 287.0807); - --primary: oklch(0.6104 0.0767 299.7335); - --primary-foreground: oklch(0.9777 0.0041 301.4256); - --secondary: oklch(0.8957 0.0265 300.2416); - --secondary-foreground: oklch(0.3651 0.0325 287.0807); - --muted: oklch(0.8906 0.0139 299.7754); - --muted-foreground: oklch(0.5288 0.0375 290.7895); - --accent: oklch(0.7889 0.0802 359.9375); - --accent-foreground: oklch(0.3394 0.0441 1.7583); - --destructive: oklch(0.6332 0.1578 22.6734); - --destructive-foreground: oklch(0.9777 0.0041 301.4256); - --border: oklch(0.8447 0.0226 300.1421); - --input: oklch(0.9329 0.0124 301.2783); - --ring: oklch(0.6104 0.0767 299.7335); - --chart-1: oklch(0.6104 0.0767 299.7335); - --chart-2: oklch(0.7889 0.0802 359.9375); - --chart-3: oklch(0.7321 0.0749 169.8670); - --chart-4: oklch(0.8540 0.0882 76.8292); - --chart-5: oklch(0.7857 0.0645 258.0839); - --sidebar: oklch(0.9554 0.0082 301.3541); - --sidebar-foreground: oklch(0.3651 0.0325 287.0807); - --sidebar-primary: oklch(0.6104 0.0767 299.7335); - --sidebar-primary-foreground: oklch(0.9777 0.0041 301.4256); - --sidebar-accent: oklch(0.7889 0.0802 359.9375); - --sidebar-accent-foreground: oklch(0.3394 0.0441 1.7583); - --sidebar-border: oklch(0.8719 0.0198 302.1690); - --sidebar-ring: oklch(0.6104 0.0767 299.7335); + /* Warm, cozy cream background */ + --background: oklch(0.98 0.008 85); + --foreground: oklch(0.25 0.02 40); + + /* Soft warm white cards */ + --card: oklch(0.995 0.005 80); + --card-foreground: oklch(0.25 0.02 40); + --popover: oklch(0.995 0.005 80); + --popover-foreground: oklch(0.25 0.02 40); + + /* Warm terracotta/rust primary - cozy and inviting */ + --primary: oklch(0.58 0.15 35); + --primary-foreground: oklch(0.98 0.008 85); + + /* Soft peach secondary */ + --secondary: oklch(0.88 0.04 60); + --secondary-foreground: oklch(0.25 0.02 40); + + /* Warm gray muted tones */ + --muted: oklch(0.92 0.01 70); + --muted-foreground: oklch(0.48 0.02 50); + + /* Warm amber accent */ + --accent: oklch(0.75 0.12 70); + --accent-foreground: oklch(0.98 0.008 85); + + /* Soft coral destructive */ + --destructive: oklch(0.6 0.18 25); + --destructive-foreground: oklch(0.98 0.008 85); + + /* Subtle warm borders */ + --border: oklch(0.88 0.015 75); + --input: oklch(0.94 0.01 75); + --ring: oklch(0.58 0.15 35); + + /* Chart colors - warm palette */ + --chart-1: oklch(0.58 0.15 35); + --chart-2: oklch(0.75 0.12 70); + --chart-3: oklch(0.65 0.15 150); + --chart-4: oklch(0.7 0.12 280); + --chart-5: oklch(0.62 0.15 320); + + --sidebar: oklch(0.96 0.008 80); + --sidebar-foreground: oklch(0.25 0.02 40); + --sidebar-primary: oklch(0.58 0.15 35); + --sidebar-primary-foreground: oklch(0.98 0.008 85); + --sidebar-accent: oklch(0.75 0.12 70); + --sidebar-accent-foreground: oklch(0.25 0.02 40); + --sidebar-border: oklch(0.88 0.015 75); + --sidebar-ring: oklch(0.58 0.15 35); + --font-sans: Geist, sans-serif; --font-serif: "Lora", Georgia, serif; --font-mono: "Fira Code", "Courier New", monospace; - --radius: 0.5rem; - --shadow-x: 1px; - --shadow-y: 2px; - --shadow-blur: 5px; - --shadow-spread: 1px; - --shadow-opacity: 0.06; - --shadow-color: hsl(0 0% 0%); - --shadow-2xs: 1px 2px 5px 1px hsl(0 0% 0% / 0.03); - --shadow-xs: 1px 2px 5px 1px hsl(0 0% 0% / 0.03); - --shadow-sm: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 1px 2px 0px hsl(0 0% 0% / 0.06); - --shadow: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 1px 2px 0px hsl(0 0% 0% / 0.06); - --shadow-md: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 2px 4px 0px hsl(0 0% 0% / 0.06); - --shadow-lg: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 4px 6px 0px hsl(0 0% 0% / 0.06); - --shadow-xl: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 8px 10px 0px hsl(0 0% 0% / 0.06); - --shadow-2xl: 1px 2px 5px 1px hsl(0 0% 0% / 0.15); - --tracking-normal: 0em; - --spacing: 0.25rem; + --radius: 0.75rem; + + /* Enhanced shadows for depth */ + --shadow-color: 25 40% 15%; + --shadow-2xs: 0 1px 2px 0 hsl(var(--shadow-color) / 0.05); + --shadow-xs: 0 1px 3px 0 hsl(var(--shadow-color) / 0.07); + --shadow-sm: 0 2px 4px -1px hsl(var(--shadow-color) / 0.08), 0 1px 2px 0 hsl(var(--shadow-color) / 0.06); + --shadow: 0 4px 6px -1px hsl(var(--shadow-color) / 0.1), 0 2px 4px -1px hsl(var(--shadow-color) / 0.06); + --shadow-md: 0 6px 12px -2px hsl(var(--shadow-color) / 0.12), 0 3px 6px -1px hsl(var(--shadow-color) / 0.08); + --shadow-lg: 0 10px 20px -3px hsl(var(--shadow-color) / 0.15), 0 4px 8px -2px hsl(var(--shadow-color) / 0.1); + --shadow-xl: 0 20px 30px -5px hsl(var(--shadow-color) / 0.18), 0 8px 16px -3px hsl(var(--shadow-color) / 0.12); + --shadow-2xl: 0 25px 50px -12px hsl(var(--shadow-color) / 0.25); } .dark { - --background: oklch(0.2166 0.0215 292.8474); - --foreground: oklch(0.9053 0.0245 293.5570); - --card: oklch(0.2544 0.0301 292.7315); - --card-foreground: oklch(0.9053 0.0245 293.5570); - --popover: oklch(0.2544 0.0301 292.7315); - --popover-foreground: oklch(0.9053 0.0245 293.5570); - --primary: oklch(0.7058 0.0777 302.0489); - --primary-foreground: oklch(0.2166 0.0215 292.8474); - --secondary: oklch(0.4604 0.0472 295.5578); - --secondary-foreground: oklch(0.9053 0.0245 293.5570); - --muted: oklch(0.2560 0.0320 294.8380); - --muted-foreground: oklch(0.6974 0.0282 300.0614); - --accent: oklch(0.3181 0.0321 308.6149); - --accent-foreground: oklch(0.8391 0.0692 2.6681); - --destructive: oklch(0.6875 0.1420 21.4566); - --destructive-foreground: oklch(0.2166 0.0215 292.8474); - --border: oklch(0.3063 0.0359 293.3367); - --input: oklch(0.2847 0.0346 291.2726); - --ring: oklch(0.7058 0.0777 302.0489); - --chart-1: oklch(0.7058 0.0777 302.0489); - --chart-2: oklch(0.8391 0.0692 2.6681); - --chart-3: oklch(0.7321 0.0749 169.8670); - --chart-4: oklch(0.8540 0.0882 76.8292); - --chart-5: oklch(0.7857 0.0645 258.0839); - --sidebar: oklch(0.1985 0.0200 293.6639); - --sidebar-foreground: oklch(0.9053 0.0245 293.5570); - --sidebar-primary: oklch(0.7058 0.0777 302.0489); - --sidebar-primary-foreground: oklch(0.2166 0.0215 292.8474); - --sidebar-accent: oklch(0.3181 0.0321 308.6149); - --sidebar-accent-foreground: oklch(0.8391 0.0692 2.6681); - --sidebar-border: oklch(0.2847 0.0346 291.2726); - --sidebar-ring: oklch(0.7058 0.0777 302.0489); + /* Deep warm charcoal background */ + --background: oklch(0.18 0.015 40); + --foreground: oklch(0.95 0.01 70); + + /* Slightly lighter warm cards */ + --card: oklch(0.22 0.02 45); + --card-foreground: oklch(0.95 0.01 70); + --popover: oklch(0.22 0.02 45); + --popover-foreground: oklch(0.95 0.01 70); + + /* Bright warm coral primary */ + --primary: oklch(0.68 0.18 40); + --primary-foreground: oklch(0.98 0.008 85); + + /* Warm muted orange secondary */ + --secondary: oklch(0.42 0.08 55); + --secondary-foreground: oklch(0.95 0.01 70); + + /* Dark warm muted tones */ + --muted: oklch(0.28 0.02 45); + --muted-foreground: oklch(0.65 0.015 60); + + /* Golden amber accent */ + --accent: oklch(0.72 0.14 75); + --accent-foreground: oklch(0.18 0.015 40); + + /* Vibrant coral destructive */ + --destructive: oklch(0.65 0.2 30); + --destructive-foreground: oklch(0.98 0.008 85); + + /* Subtle warm borders */ + --border: oklch(0.32 0.025 45); + --input: oklch(0.28 0.02 45); + --ring: oklch(0.68 0.18 40); + + /* Chart colors - warm dark palette */ + --chart-1: oklch(0.68 0.18 40); + --chart-2: oklch(0.72 0.14 75); + --chart-3: oklch(0.65 0.15 150); + --chart-4: oklch(0.7 0.12 280); + --chart-5: oklch(0.62 0.15 320); + + --sidebar: oklch(0.16 0.02 40); + --sidebar-foreground: oklch(0.95 0.01 70); + --sidebar-primary: oklch(0.68 0.18 40); + --sidebar-primary-foreground: oklch(0.98 0.008 85); + --sidebar-accent: oklch(0.72 0.14 75); + --sidebar-accent-foreground: oklch(0.18 0.015 40); + --sidebar-border: oklch(0.28 0.02 45); + --sidebar-ring: oklch(0.68 0.18 40); + --font-sans: Geist, sans-serif; --font-serif: "Lora", Georgia, serif; --font-mono: "Fira Code", "Courier New", monospace; - --radius: 0.5rem; - --shadow-x: 1px; - --shadow-y: 2px; - --shadow-blur: 5px; - --shadow-spread: 1px; - --shadow-opacity: 0.06; - --shadow-color: hsl(0 0% 0%); - --shadow-2xs: 1px 2px 5px 1px hsl(0 0% 0% / 0.03); - --shadow-xs: 1px 2px 5px 1px hsl(0 0% 0% / 0.03); - --shadow-sm: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 1px 2px 0px hsl(0 0% 0% / 0.06); - --shadow: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 1px 2px 0px hsl(0 0% 0% / 0.06); - --shadow-md: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 2px 4px 0px hsl(0 0% 0% / 0.06); - --shadow-lg: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 4px 6px 0px hsl(0 0% 0% / 0.06); - --shadow-xl: 1px 2px 5px 1px hsl(0 0% 0% / 0.06), 1px 8px 10px 0px hsl(0 0% 0% / 0.06); - --shadow-2xl: 1px 2px 5px 1px hsl(0 0% 0% / 0.15); + --radius: 0.75rem; + + /* Enhanced shadows for dark mode depth */ + --shadow-color: 0 0% 0%; + --shadow-2xs: 0 1px 2px 0 hsl(var(--shadow-color) / 0.3); + --shadow-xs: 0 1px 3px 0 hsl(var(--shadow-color) / 0.35); + --shadow-sm: 0 2px 4px -1px hsl(var(--shadow-color) / 0.4), 0 1px 2px 0 hsl(var(--shadow-color) / 0.3); + --shadow: 0 4px 6px -1px hsl(var(--shadow-color) / 0.45), 0 2px 4px -1px hsl(var(--shadow-color) / 0.35); + --shadow-md: 0 6px 12px -2px hsl(var(--shadow-color) / 0.5), 0 3px 6px -1px hsl(var(--shadow-color) / 0.4); + --shadow-lg: 0 10px 20px -3px hsl(var(--shadow-color) / 0.55), 0 4px 8px -2px hsl(var(--shadow-color) / 0.45); + --shadow-xl: 0 20px 30px -5px hsl(var(--shadow-color) / 0.6), 0 8px 16px -3px hsl(var(--shadow-color) / 0.5); + --shadow-2xl: 0 25px 50px -12px hsl(var(--shadow-color) / 0.7); } @layer base { @@ -306,3 +336,89 @@ -webkit-text-fill-color: transparent; background-clip: text; } + +/* Cozy card effect */ +.cozy-card { + background: hsl(var(--card)); + border: 1px solid hsl(var(--border) / 0.5); + border-radius: var(--radius); + box-shadow: var(--shadow-md); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.cozy-card:hover { + box-shadow: var(--shadow-xl); + transform: translateY(-4px); + border-color: hsl(var(--primary) / 0.2); +} + +/* Warm glow effect */ +.warm-glow { + position: relative; +} + +.warm-glow::before { + content: ''; + position: absolute; + inset: -20px; + background: radial-gradient(circle at center, hsl(var(--primary) / 0.15) 0%, transparent 70%); + border-radius: 50%; + filter: blur(30px); + z-index: -1; + opacity: 0; + transition: opacity 0.5s ease; +} + +.warm-glow:hover::before { + opacity: 1; +} + +/* Subtle pattern background */ +.pattern-bg { + background-image: + radial-gradient(circle at 20px 20px, hsl(var(--primary) / 0.03) 1px, transparent 1px); + background-size: 40px 40px; +} + +/* Frosted glass effect - enhanced */ +.frosted-glass { + background: linear-gradient(135deg, + hsl(var(--card) / 0.7) 0%, + hsl(var(--card) / 0.5) 100%); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + border: 1px solid hsl(var(--border) / 0.3); + box-shadow: + 0 8px 32px 0 hsl(var(--shadow-color) / 0.1), + inset 0 1px 0 0 hsl(255 255 255 / 0.05); +} + +/* Responsive text sizes */ +@media (max-width: 640px) { + html { + font-size: 14px; + } +} + +@media (min-width: 1024px) { + html { + font-size: 16px; + } +} + +/* Better focus states */ +*:focus-visible { + outline: 2px solid hsl(var(--ring)); + outline-offset: 2px; + border-radius: 4px; +} + +/* Smooth hover transitions for interactive elements */ +button, a, input, select, textarea { + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Enhanced button styles */ +button:active { + transform: scale(0.98); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b553272..6f29e11 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -37,7 +37,7 @@ export default function RootLayout({
-
+
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx index f5a5a55..f868dea 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -29,45 +29,49 @@ export default function Home() { }, []); return ( -
+
{/* Hero Section */} -
- {/* Enhanced gradient background */} +
+ {/* Enhanced cozy gradient background */}
-
-
-
-
+
+
+
+
-
-
- {/* Icon with animation */} +
+
+ {/* Icon with enhanced animation */}
-
-
-
- +
+
+
+
{/* Heading with stagger animation */} -
-

- BookMarked +
+

+ BookMarked

-

- Your personal digital library. Read, organize, and sync your books across all devices. +

+ Your personal sanctuary for digital reading. Curate, organize, and enjoy your books across all devices with effortless sync.

- {/* CTA Button */} -
-
@@ -75,60 +79,69 @@ export default function Home() {

- {/* Features Section */} -
-
-
- - -
- + {/* Features Section with enhanced design */} +
+
+
+

+ Everything you need for a cozy reading experience +

+

+ Thoughtfully designed features to make digital reading delightful +

+
+ +
+ + +
+
-
-

Cloud Sync

-

+

+

Cloud Sync

+

Your library and reading progress synced seamlessly across all your devices.

- - -
- + + +
+
-
-

Beautiful Reader

-

+

+

Beautiful Reader

+

Enjoy a distraction-free reading experience with customizable themes.

- - -
- + + +
+
-
-

Offline Ready

-

+

+

Offline Ready

+

Read your books anytime, anywhere with full offline support via PWA.

- - -
- + + +
+
-
-

Private & Secure

-

+

+

Private & Secure

+

Your books and data are encrypted and stored securely in your account.

diff --git a/src/components/header.tsx b/src/components/header.tsx index 0df61d4..bb30ac8 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -86,37 +86,47 @@ export function Header() { } return ( -
-
-
- +
+
+
+
-
-
- +
+
+
- BookMarked + BookMarked - -
-
+
{!isOnline && ( - + Offline )} @@ -125,21 +135,21 @@ export function Header() { variant="ghost" size="sm" onClick={handleSignOut} - className="flex items-center gap-1.5 cursor-pointer smooth-transition hover:bg-destructive/10 hover:text-destructive" + className="flex items-center gap-1.5 cursor-pointer smooth-transition hover:bg-destructive/15 hover:text-destructive rounded-lg h-9 px-2 sm:px-3" > - Sign Out + Sign Out ) : ( )} From 8058732c50fde35d2f15694ad073266e5eb03211 Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 06:06:16 +0000 Subject: [PATCH 3/7] refactor(ui): modernize layout, fonts, and fix text visibility Apply modern asymmetric layouts, bento grids, and new font families across the homepage and header. Ensure all text is readable in both light and dark modes (fixes brand/gradient text). Dramatically enhance structure, style, and visual hierarchy for a contemporary feel. - Redesigned home page with modern hero, bento layout, and cta - Switched to Inter, Playfair Display, and JetBrains Mono font stack - Updated header with visible brand text and style coherence - CSS clarity: all text uses text-foreground, improve gradient fallback --- src/app/globals.css | 22 ++- src/app/layout.tsx | 27 +++- src/app/page.tsx | 277 +++++++++++++++++++++++++++----------- src/components/header.tsx | 52 +++---- 4 files changed, 257 insertions(+), 121 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 5db2f0d..572847b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -200,7 +200,16 @@ } body { @apply bg-background text-foreground; - font-family: var(--font-instrument-sans), ui-sans-serif, system-ui, sans-serif; + font-family: var(--font-inter), ui-sans-serif, system-ui, sans-serif; + } + + h1, h2, h3, h4, h5, h6 { + font-family: var(--font-playfair), Georgia, serif; + letter-spacing: -0.025em; + } + + code, pre, kbd { + font-family: var(--font-jetbrains), 'Courier New', monospace; } } @@ -329,12 +338,21 @@ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } -/* Gradient text */ +/* Gradient text - fixed for visibility */ .gradient-text { background: linear-gradient(135deg, hsl(var(--primary)) 0%, hsl(var(--accent)) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; + /* Fallback for browsers that don't support background-clip */ + color: hsl(var(--primary)); +} + +/* Visible text - no gradient issues */ +.brand-text { + color: hsl(var(--foreground)); + font-weight: 800; + letter-spacing: -0.02em; } /* Cozy card effect */ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6f29e11..bc5dd82 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,14 +1,26 @@ import type { Metadata } from "next"; -import { Instrument_Sans } from "next/font/google"; +import { Inter, Playfair_Display, JetBrains_Mono } from "next/font/google"; import "./globals.css"; import { ThemeProvider } from "@/components/theme-provider"; import { Header } from "@/components/header"; import { ServiceWorkerProvider } from "@/components/service-worker-provider"; -const instrumentSans = Instrument_Sans({ - variable: "--font-instrument-sans", +const inter = Inter({ + variable: "--font-inter", + subsets: ["latin"], + display: "swap", +}); + +const playfair = Playfair_Display({ + variable: "--font-playfair", + subsets: ["latin"], + weight: ["400", "500", "600", "700", "800", "900"], + display: "swap", +}); + +const jetbrains = JetBrains_Mono({ + variable: "--font-jetbrains", subsets: ["latin"], - weight: ["400", "500", "600", "700"], display: "swap", }); @@ -32,12 +44,15 @@ export default function RootLayout({ }>) { return ( - +
-
+
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx index f868dea..4873f51 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; import { supabase } from "@/lib/supabase"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; -import { BookOpen, ArrowRight, Sparkles, Cloud, Lock, Zap } from "lucide-react"; +import { BookOpen, ArrowRight, Sparkles, Cloud, Lock, Zap, Library, Bookmark, Star } from "lucide-react"; import Link from "next/link"; export default function Home() { @@ -29,120 +29,208 @@ export default function Home() { }, []); return ( -
- {/* Hero Section */} -
- {/* Enhanced cozy gradient background */} +
+ {/* Hero Section - Asymmetric Modern Layout */} +
+ {/* Modern gradient mesh background */}
-
-
-
-
+
+
- -
-
- {/* Icon with enhanced animation */} -
-
-
-
- -
+ +
+
+ {/* Left Content */} +
+
+ + Your Digital Reading Companion
-
- - {/* Heading with stagger animation */} -
-

- BookMarked + +

+ Read +
+ Anywhere, +
+ Anytime

-

- Your personal sanctuary for digital reading. Curate, organize, and enjoy your books across all devices with effortless sync. + +

+ Your personal library in the cloud. Organize, read, and sync your books seamlessly across all devices.

+ +
+ + +
+ + {/* Stats */} +
+
+
Free
+
Forever Plan
+
+
+
Unlimited
+
Storage
+
+
+
100%
+
Secure
+
+
- {/* CTA Button with extra polish */} -
- + {/* Right Visual */} +
+
+ {/* Decorative cards */} +
+ + +
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+
+
+
+
+
+
- {/* Features Section with enhanced design */} -
-
-
-

- Everything you need for a cozy reading experience + {/* Features Section - Bento Grid Layout */} +
+
+
+

+ Everything You Need

-

- Thoughtfully designed features to make digital reading delightful +

+ Powerful features designed for the modern reader

-
- - -
- + {/* Bento Grid */} +
+ {/* Large Featured Card */} + + +
+
+ +
+
+

Seamless Cloud Sync

+

+ Your entire library syncs automatically across all your devices. Start reading on your phone, continue on your tablet, and finish on your desktop without missing a beat. +

+
-
-

Cloud Sync

-

- Your library and reading progress synced seamlessly across all your devices. -

+
+
+
+
+ Real-time sync +
+
+
+ End-to-end encrypted +
+
+ {/* Smaller Cards */} - -
- + +
+
-
-

Beautiful Reader

-

- Enjoy a distraction-free reading experience with customizable themes. +

+

Beautiful Reader

+

+ Distraction-free reading with customizable themes and layouts.

- -
- + +
+
-
-

Offline Ready

-

- Read your books anytime, anywhere with full offline support via PWA. +

+

Lightning Fast

+

+ Optimized performance with instant page loads and smooth navigation.

- - -
- + + +
+
-
-

Private & Secure

-

- Your books and data are encrypted and stored securely in your account. +

+

Privacy First

+

+ Your books and data are encrypted and stored securely. We respect your privacy and never track your reading habits.

@@ -150,6 +238,37 @@ export default function Home() {
+ + {/* CTA Section */} +
+
+ +
+ +
+

+ Start Your Reading Journey Today +

+

+ Join thousands of readers who trust BookMarked for their digital library +

+
+
+ +
+
+
+
+

); } diff --git a/src/components/header.tsx b/src/components/header.tsx index bb30ac8..b1d0efe 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -16,7 +16,6 @@ export function Header() { useEffect(() => { setMounted(true) - // Check auth status const checkAuth = async () => { const { data: { user } } = await supabase.auth.getUser() setSignedIn(!!user) @@ -24,12 +23,10 @@ export function Header() { checkAuth() - // Listen for auth changes const { data: subscription } = supabase.auth.onAuthStateChange((_event, session) => { setSignedIn(!!session) }) - // Online/offline listeners const handleOnline = () => setIsOnline(true) const handleOffline = () => setIsOnline(false) if (typeof window !== 'undefined') { @@ -54,31 +51,16 @@ export function Header() { if (!mounted) { return ( -
-
-
- -
- BookMarked - - - +
+
+
+
+
+ BookMarked +
-
-
+
+
@@ -87,16 +69,18 @@ export function Header() { return (
-
+
-
+
- BookMarked + + BookMarked +

-

+

Your personal library in the cloud. Organize, read, and sync your books seamlessly across all devices.

@@ -82,19 +82,19 @@ export default function Home() {
- {/* Stats */} -
-
-
Free
-
Forever Plan
+ {/* Features List */} +
+
+
+ Cloud Syncing
-
-
Unlimited
-
Storage
+
+
+ Offline Reading
-
-
100%
-
Secure
+
+
+ Progress Tracking
@@ -157,7 +157,7 @@ export default function Home() {

Everything You Need

-

+

Powerful features designed for the modern reader

@@ -249,7 +249,7 @@ export default function Home() {

Start Your Reading Journey Today

-

+

Join thousands of readers who trust BookMarked for their digital library

diff --git a/src/components/header.tsx b/src/components/header.tsx index b1d0efe..82fc8a9 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -1,7 +1,7 @@ "use client" import Link from "next/link" -import { BookOpen, Home, Library, LogIn, LogOut } from "lucide-react" +import { BookOpen, Home, Library, LogIn, LogOut, Menu, X } from "lucide-react" import { Button } from "@/components/ui/button" import { ThemeToggle } from "@/components/theme-toggle" import { Separator } from "@/components/ui/separator" @@ -12,6 +12,7 @@ export function Header() { const [mounted, setMounted] = useState(false) const [signedIn, setSignedIn] = useState(null) const [isOnline, setIsOnline] = useState(true) + const [mobileMenuOpen, setMobileMenuOpen] = useState(false) useEffect(() => { setMounted(true) @@ -51,8 +52,8 @@ export function Header() { if (!mounted) { return ( -
-
+
+
@@ -68,78 +69,161 @@ export function Header() { } return ( -
-
-
- -
-
-
- + <> +
+
+
+ +
+
+
+ +
+ + BookMarked + + + + + + {/* Desktop Navigation */} + +
+ +
+ {!isOnline && ( + + Offline + + )} + + {/* Desktop Auth Buttons */} +
+ {signedIn ? ( + + ) : ( + + )}
- - BookMarked - - - - -
-
- {!isOnline && ( - - Offline - - )} - {signedIn ? ( - - ) : ( - - )} - +
-
-
+ + {/* Mobile Menu */} + {mobileMenuOpen && ( +
+ +
+ )} +
+ ) } From 5a1ce3b6cd019773c09b8bd48d4d2ebce24a636c Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 06:22:02 +0000 Subject: [PATCH 5/7] fix(layout): ensure Instrument Sans font applies sitewide Ensure Instrument Sans font is properly set as the main font for body text by including its className in the body element in layout.tsx. Resolves issue where fallback fonts were displaying instead of Instrument Sans, maintaining consistent sitewide typography. --- src/app/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 412f29d..84f33cc 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -40,7 +40,7 @@ export default function RootLayout({ return ( From 827bbb59977f35260bed57736fca753f43b991a7 Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 06:31:55 +0000 Subject: [PATCH 6/7] feat(nav): enhance mobile collapsed menu with overlay and animation - Improves mobile navigation experience with a modal backdrop overlay - Adds smooth slide-down animation and disables body scroll when open - Updates menu layout and icons for modern, touch-friendly usability - Closes mobile menu on overlay click or Escape key for accessibility --- src/app/globals.css | 15 ++++++ src/components/header.tsx | 111 ++++++++++++++++++++++++++------------ 2 files changed, 93 insertions(+), 33 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 5ff26b5..c13ca4f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -283,6 +283,17 @@ } } +@keyframes slide-down { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + /* Utility classes */ .animate-fade-in-up { animation: fade-in-up 0.6s ease-out forwards; @@ -300,6 +311,10 @@ animation: slide-in-left 0.6s ease-out forwards; } +.animate-slide-down { + animation: slide-down 0.3s ease-out forwards; +} + .animation-delay-200 { animation-delay: 0.2s; } diff --git a/src/components/header.tsx b/src/components/header.tsx index 82fc8a9..1b5343d 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -36,14 +36,31 @@ export function Header() { window.addEventListener('offline', handleOffline) } + // Close mobile menu on Escape key + const handleEscape = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + setMobileMenuOpen(false) + } + } + + if (mobileMenuOpen) { + document.addEventListener('keydown', handleEscape) + // Prevent body scroll when menu is open + document.body.style.overflow = 'hidden' + } else { + document.body.style.overflow = '' + } + return () => { subscription.subscription.unsubscribe() if (typeof window !== 'undefined') { window.removeEventListener('online', handleOnline) window.removeEventListener('offline', handleOffline) } + document.removeEventListener('keydown', handleEscape) + document.body.style.overflow = '' } - }, []) + }, [mobileMenuOpen]) const handleSignOut = async () => { await supabase.auth.signOut() @@ -70,6 +87,14 @@ export function Header() { return ( <> + {/* Backdrop for mobile menu */} + {mobileMenuOpen && ( +
setMobileMenuOpen(false)} + /> + )} +
@@ -168,32 +193,47 @@ export function Header() { {/* Mobile Menu */} {mobileMenuOpen && ( -
-