From 816476ed024d72f9e460377e7ac7d954ce274bf0 Mon Sep 17 00:00:00 2001 From: Jeet Debnath Date: Tue, 14 Apr 2026 15:26:13 +0530 Subject: [PATCH] added liquid glass theme --- src/App.css | 279 +++++++++++++++++++++++++++++++++++++ src/index.css | 25 ++++ src/main.tsx | 4 + src/pages/SettingsPage.tsx | 21 ++- 4 files changed, 323 insertions(+), 6 deletions(-) diff --git a/src/App.css b/src/App.css index 8992d2a..80bb605 100644 --- a/src/App.css +++ b/src/App.css @@ -1580,6 +1580,12 @@ .settings-theme-dot-dark { background: #1a1a1a; } +.settings-theme-dot-glass { + background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(209,250,229,0.7) 50%, rgba(167,243,208,0.5) 100%); + border: 2px solid rgba(255, 255, 255, 0.8); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} .settings-theme-dot:hover:not(:disabled) { transform: scale(1.15); } @@ -2997,6 +3003,279 @@ color: #9ca3af; } +/* ============================ + LIQUID GLASS THEME + ============================ */ + +/* -- Pages must be transparent so body background shows through -- */ +[data-theme="liquid-glass"] .home-page, +[data-theme="liquid-glass"] .history-page, +[data-theme="liquid-glass"] .settings-page { + background: transparent; +} + +/* -- Glass surface applied to all card/surface elements -- */ +[data-theme="liquid-glass"] .journal-card, +[data-theme="liquid-glass"] .calendar-card, +[data-theme="liquid-glass"] .entry-card, +[data-theme="liquid-glass"] .entry-modal, +[data-theme="liquid-glass"] .confirm-modal, +[data-theme="liquid-glass"] .settings-profile, +[data-theme="liquid-glass"] .settings-card, +[data-theme="liquid-glass"] .settings-tutorial-btn, +[data-theme="liquid-glass"] .settings-clear-btn, +[data-theme="liquid-glass"] .settings-signout-btn, +[data-theme="liquid-glass"] .bottom-nav, +[data-theme="liquid-glass"] .lp__form { + background: var(--glass-bg); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border: var(--glass-border); + box-shadow: var(--glass-shadow); +} + +/* -- Unified shadow (no individual overrides needed) -- */ +[data-theme="liquid-glass"] .journal-card, +[data-theme="liquid-glass"] .calendar-card, +[data-theme="liquid-glass"] .entry-card, +[data-theme="liquid-glass"] .settings-profile, +[data-theme="liquid-glass"] .settings-card { + box-shadow: var(--glass-shadow); +} + +/* -- Bottom nav glass -- */ +[data-theme="liquid-glass"] .bottom-nav { + box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.5), 0 -8px 32px rgba(0, 0, 0, 0.1); +} + +/* -- Text colors — dark & crisp for readability on glass -- */ +[data-theme="liquid-glass"] .journal-prompt, +[data-theme="liquid-glass"] .settings-header-text h1, +[data-theme="liquid-glass"] .history-header-text h1, +[data-theme="liquid-glass"] .settings-profile-name, +[data-theme="liquid-glass"] .settings-item-title, +[data-theme="liquid-glass"] .calendar-month, +[data-theme="liquid-glass"] .entry-title { + color: #0f172a; +} + +[data-theme="liquid-glass"] .journal-date { + color: #16a34a; +} + +[data-theme="liquid-glass"] .settings-subtitle, +[data-theme="liquid-glass"] .history-subtitle, +[data-theme="liquid-glass"] .settings-item-subtitle, +[data-theme="liquid-glass"] .settings-section-title, +[data-theme="liquid-glass"] .entry-preview, +[data-theme="liquid-glass"] .entry-date, +[data-theme="liquid-glass"] .entry-time, +[data-theme="liquid-glass"] .recent-entries-title, +[data-theme="liquid-glass"] .calendar-weekday { + color: #334155; +} + +[data-theme="liquid-glass"] .journal-title-input, +[data-theme="liquid-glass"] .journal-entry-textarea { + color: #1e293b; +} + +[data-theme="liquid-glass"] .journal-title-input::placeholder, +[data-theme="liquid-glass"] .journal-entry-textarea::placeholder { + color: rgba(30, 41, 59, 0.45); +} + +[data-theme="liquid-glass"] .journal-title-input { + border-bottom-color: rgba(255, 255, 255, 0.4); +} + +[data-theme="liquid-glass"] .journal-title-input:focus { + border-bottom-color: #16a34a; +} + +/* -- Settings buttons text -- */ +[data-theme="liquid-glass"] .settings-tutorial-btn { + color: #0f172a; +} + +[data-theme="liquid-glass"] .settings-clear-btn { + color: #b91c1c; +} + +[data-theme="liquid-glass"] .settings-signout-btn { + color: #475569; +} + +/* -- Settings buttons hover -- */ +[data-theme="liquid-glass"] .settings-tutorial-btn:hover { + background: rgba(255, 255, 255, 0.35); +} +[data-theme="liquid-glass"] .settings-clear-btn:hover { + background: rgba(254, 202, 202, 0.35); +} +[data-theme="liquid-glass"] .settings-signout-btn:hover { + background: rgba(255, 255, 255, 0.3); + color: #1e293b; +} + +/* -- Settings item hover -- */ +[data-theme="liquid-glass"] .settings-item-button:hover { + background: rgba(255, 255, 255, 0.28); +} + +/* -- Settings divider -- */ +[data-theme="liquid-glass"] .settings-divider { + background: rgba(255, 255, 255, 0.45); +} + +/* -- Settings theme dot -- */ +[data-theme="liquid-glass"] .settings-theme-dot { + border-color: rgba(0, 0, 0, 0.12); +} +[data-theme="liquid-glass"] .settings-theme-dot-active { + border-color: #16a34a; + box-shadow: 0 0 0 2px #16a34a; +} + +/* -- Settings icon backgrounds -- */ +[data-theme="liquid-glass"] .settings-item-icon-green { + background: rgba(34, 197, 94, 0.2); + color: #15803d; +} +[data-theme="liquid-glass"] .settings-item-icon-gray { + background: rgba(100, 116, 139, 0.18); + color: #475569; +} +[data-theme="liquid-glass"] .settings-item-icon-orange { + background: rgba(251, 146, 60, 0.2); + color: #c2410c; +} +[data-theme="liquid-glass"] .settings-item-icon-blue { + background: rgba(59, 130, 246, 0.18); + color: #1d4ed8; +} +[data-theme="liquid-glass"] .settings-item-icon-purple { + background: rgba(139, 92, 246, 0.18); + color: #6d28d9; +} + +/* -- Settings misc -- */ +[data-theme="liquid-glass"] .settings-toggle-slider { + background: rgba(0, 0, 0, 0.2); +} +[data-theme="liquid-glass"] .settings-toggle input:checked + .settings-toggle-slider { + background: #16a34a; +} +[data-theme="liquid-glass"] .settings-item-arrow { + color: #334155; +} +[data-theme="liquid-glass"] .settings-enc { + color: rgba(15, 23, 42, 0.45); +} +[data-theme="liquid-glass"] .settings-edit-btn { + background: rgba(34, 197, 94, 0.2); + color: #15803d; +} + +/* -- Calendar -- */ +[data-theme="liquid-glass"] .calendar-day { + color: #334155; +} +[data-theme="liquid-glass"] .calendar-day:not(.calendar-day-empty):hover { + background: rgba(255, 255, 255, 0.4); + color: #0f172a; +} +[data-theme="liquid-glass"] .calendar-day-has-entry { + background: rgba(34, 197, 94, 0.22); + color: #15803d; +} +[data-theme="liquid-glass"] .calendar-day-today { + background: #16a34a; + color: #fff; +} +[data-theme="liquid-glass"] .calendar-nav-btn:hover { + background: rgba(255, 255, 255, 0.35); + color: #0f172a; +} + +/* -- Entry card -- */ +[data-theme="liquid-glass"] .entry-card { + border-left-color: rgba(22, 163, 74, 0.5); +} +[data-theme="liquid-glass"] .entry-card:hover { + background: rgba(255, 255, 255, 0.28); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.14), 0 1px 0 rgba(255, 255, 255, 0.7) inset; +} + +/* -- Entry modal -- */ +[data-theme="liquid-glass"] .entry-modal { + border-top-color: #16a34a; +} +[data-theme="liquid-glass"] .entry-modal-title { + color: #0f172a; +} +[data-theme="liquid-glass"] .entry-modal-content { + color: #1e293b; +} +[data-theme="liquid-glass"] .entry-modal-date, +[data-theme="liquid-glass"] .entry-modal-time { + color: #475569; +} +[data-theme="liquid-glass"] .entry-modal-badge { + background: rgba(34, 197, 94, 0.2); + color: #15803d; +} +[data-theme="liquid-glass"] .entry-modal-close { + background: rgba(255, 255, 255, 0.35); + color: #475569; +} +[data-theme="liquid-glass"] .entry-modal-close:hover { + background: rgba(255, 255, 255, 0.5); + color: #0f172a; +} + +/* -- Confirm/modal overlays -- */ +[data-theme="liquid-glass"] .confirm-modal-overlay, +[data-theme="liquid-glass"] .entry-modal-overlay { + background: rgba(15, 23, 42, 0.2); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); +} + +/* -- Bottom nav -- */ +[data-theme="liquid-glass"] .bottom-nav-btn { + color: #475569; +} +[data-theme="liquid-glass"] .bottom-nav-btn:hover { + color: #15803d; + background: rgba(255, 255, 255, 0.3); +} +[data-theme="liquid-glass"] .bottom-nav-btn-active { + background: #16a34a; + color: #fff; +} + +/* -- Write button -- */ +[data-theme="liquid-glass"] .journal-write-btn { + background: #16a34a; + box-shadow: 0 4px 16px rgba(22, 163, 74, 0.35); +} +[data-theme="liquid-glass"] .journal-write-btn:hover:not(:disabled) { + background: #15803d; + box-shadow: 0 6px 24px rgba(22, 163, 74, 0.45); +} + +/* -- Desktop sidebar nav glass -- */ +@media (min-width: 860px) { + [data-theme="liquid-glass"] .bottom-nav { + background: var(--glass-bg); + border-right-color: rgba(255, 255, 255, 0.4); + } + [data-theme="liquid-glass"] .bottom-nav-brand { + border-bottom-color: rgba(255, 255, 255, 0.4); + } +} + [data-theme="dark"] .clock-picker__mode-btn--active { background: #4ade80; border-color: #4ade80; diff --git a/src/index.css b/src/index.css index 65d3aaa..9a25f2a 100644 --- a/src/index.css +++ b/src/index.css @@ -96,3 +96,28 @@ button:focus-visible { [data-theme="dark"] body { background: #0a0a0a; } + +/* ── Liquid Glass theme root overrides ───────────────────── */ +[data-theme="liquid-glass"] { + --glass-bg: rgba(255, 255, 255, 0.18); + --glass-blur: blur(28px) saturate(200%) brightness(1.05); + --glass-border: 1px solid rgba(255, 255, 255, 0.55); + --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 1px 0 rgba(255, 255, 255, 0.7) inset; + --color-primary: #16a34a; + --color-primary-hover: #15803d; + --color-bg-soft: transparent; + --color-surface: var(--glass-bg); + --color-accent-light: rgba(220, 252, 231, 0.4); + --color-text: #0f172a; + --color-text-muted: #334155; + --color-border: rgba(255, 255, 255, 0.4); + + color: var(--color-text); + background-color: transparent; + caret-color: #16a34a; +} + +/* Same bg as light theme when no custom image is set */ +[data-theme="liquid-glass"] body:not(.gj-has-bg) { + background: #eef6ee; +} diff --git a/src/main.tsx b/src/main.tsx index 63bd4ba..cba487b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,6 +4,10 @@ import './index.css' import App from './App.tsx' import { listenForegroundMessages } from './hooks/useReminder' +// Apply saved theme immediately to avoid flash +const savedTheme = localStorage.getItem('gj-theme') || 'light' +document.documentElement.setAttribute('data-theme', savedTheme) + if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js') diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index 71415f3..6d8f1bd 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -54,8 +54,8 @@ export default function SettingsPage() { const { user, userId, mongoUser, signOut, loading, refreshMongoUser } = useAuth() // const [passcodeEnabled, setPasscodeEnabled] = useState(false) // Passcode lock — disabled for now // const [faceIdEnabled, setFaceIdEnabled] = useState(false) // Face ID — disabled for now - const [theme, setTheme] = useState<'light' | 'dark'>(() => { - return (localStorage.getItem('gj-theme') as 'light' | 'dark') || 'light' + const [theme, setTheme] = useState<'light' | 'dark' | 'liquid-glass'>(() => { + return (localStorage.getItem('gj-theme') as 'light' | 'dark' | 'liquid-glass') || 'light' }) const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null) @@ -229,7 +229,7 @@ export default function SettingsPage() { } // Apply theme to DOM - const applyTheme = useCallback((t: 'light' | 'dark') => { + const applyTheme = useCallback((t: 'light' | 'dark' | 'liquid-glass') => { document.documentElement.setAttribute('data-theme', t) localStorage.setItem('gj-theme', t) }, []) @@ -239,10 +239,11 @@ export default function SettingsPage() { applyTheme(theme) }, [theme, applyTheme]) - const handleThemeChange = (newTheme: 'light' | 'dark') => { + const handleThemeChange = (newTheme: 'light' | 'dark' | 'liquid-glass') => { setTheme(newTheme) applyTheme(newTheme) - setMessage({ type: 'success', text: `Switched to ${newTheme === 'light' ? 'Light' : 'Dark'} theme` }) + const label = newTheme === 'light' ? 'Light' : newTheme === 'dark' ? 'Dark' : 'Liquid Glass' + setMessage({ type: 'success', text: `Switched to ${label} theme` }) setTimeout(() => setMessage(null), 2000) } @@ -560,7 +561,9 @@ export default function SettingsPage() {

Theme

-

Currently: {theme === 'light' ? 'Light' : 'Dark'}

+

+ Currently: {theme === 'light' ? 'Light' : theme === 'dark' ? 'Dark' : 'Liquid Glass'} +

+