diff --git a/documentation/FEATURES.md b/documentation/FEATURES.md index a1ff48f..6c525b7 100644 --- a/documentation/FEATURES.md +++ b/documentation/FEATURES.md @@ -266,6 +266,8 @@ date: {{date}} | `Ctrl+Alt+F` | `Cmd+Option+F` | New folder | | `Ctrl+Z` | `Cmd+Z` | Undo | | `Ctrl+Y` or `Ctrl+Shift+Z` | `Cmd+Y` or `Cmd+Shift+Z` | Redo | +| `Ctrl+Shift+Z` | `Cmd+Shift+Z` | Toggle Zen Mode | +| `Esc` | `Esc` | Exit Zen Mode | | `F3` | `F3` | Next search match | | `Shift+F3` | `Shift+F3` | Previous search match | @@ -278,6 +280,18 @@ date: {{date}} | `Ctrl+K` | `Cmd+K` | Insert link | `[text](url)` | | `Ctrl+Alt+T` | `Cmd+Option+T` | Insert table | 3x3 table placeholder | +## 🧘 Zen Mode + +Full immersive distraction-free writing experience: + +- **Full screen** - Uses browser Fullscreen API for true immersion +- **Hidden UI** - Sidebar, toolbar, and stats bar disappear +- **Centered editor** - Comfortable width for optimal reading +- **Larger text** - 18px font size with relaxed line spacing +- **Quick access** - Button in toolbar or `Ctrl+Shift+Z` shortcut +- **Easy exit** - Press `Esc`, click exit button, or use shortcut again +- **State preserved** - Returns to your previous view mode on exit + ## 🚀 Performance - **Instant loading** - No lag, no loading spinners diff --git a/frontend/app.js b/frontend/app.js index 3b7a0a4..fe8b3ab 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -56,6 +56,8 @@ function noteApp() { isSaving: false, lastSaved: false, linkCopied: false, + zenMode: false, + previousViewMode: 'split', saveTimeout: null, // Theme state @@ -468,6 +470,18 @@ function noteApp() { e.preventDefault(); this.insertTable(); } + + // Ctrl/Cmd + Shift + Z for Zen mode (only when note is open) + if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'Z') { + e.preventDefault(); + this.toggleZenMode(); + } + } + + // Escape to exit Zen mode (works anywhere) + if (e.key === 'Escape' && this.zenMode) { + e.preventDefault(); + this.toggleZenMode(); } }); } @@ -482,6 +496,15 @@ function noteApp() { } }); } + + // Listen for fullscreen changes (to sync zen mode state) + document.addEventListener('fullscreenchange', () => { + if (!document.fullscreenElement && this.zenMode) { + // User exited fullscreen manually, exit zen mode too + this.zenMode = false; + this.viewMode = this.previousViewMode; + } + }); }, // Load app configuration @@ -4043,6 +4066,55 @@ function noteApp() { }, 1500); }, + // Toggle Zen Mode (full immersive writing experience) + async toggleZenMode() { + if (!this.zenMode) { + // Entering Zen Mode + this.previousViewMode = this.viewMode; + this.viewMode = 'edit'; + this.mobileSidebarOpen = false; + this.zenMode = true; + + // Request fullscreen + try { + const elem = document.documentElement; + if (elem.requestFullscreen) { + await elem.requestFullscreen(); + } else if (elem.webkitRequestFullscreen) { + await elem.webkitRequestFullscreen(); + } else if (elem.msRequestFullscreen) { + await elem.msRequestFullscreen(); + } + } catch (e) { + // Fullscreen not supported or denied, continue anyway + console.log('Fullscreen not available:', e); + } + + // Focus editor after transition + setTimeout(() => { + const editor = document.getElementById('note-editor'); + if (editor) editor.focus(); + }, 300); + } else { + // Exiting Zen Mode + this.zenMode = false; + this.viewMode = this.previousViewMode; + + // Exit fullscreen + try { + if (document.exitFullscreen) { + await document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + await document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + await document.msExitFullscreen(); + } + } catch (e) { + console.log('Exit fullscreen error:', e); + } + } + }, + // Homepage folder navigation methods goToHomepageFolder(folderPath) { this.showGraph = false; // Close graph when navigating diff --git a/frontend/index.html b/frontend/index.html index 663b764..609b74c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -470,6 +470,67 @@ background-color: var(--bg-primary); z-index: 0; } + + /* Zen Mode Styles */ + .zen-mode-active { + background-color: var(--bg-primary); + } + .zen-mode-active .zen-hide { + display: none !important; + } + .zen-mode-active .zen-editor-container { + width: 100%; + margin: 0; + padding: 2rem 4rem; + height: 100vh; + } + .zen-mode-active .zen-editor-container .editor-wrapper { + background-color: var(--bg-primary); + } + .zen-mode-active .zen-editor-container .editor-textarea { + font-size: 18px; + line-height: 1.8; + } + .zen-mode-active .zen-editor-container .syntax-overlay { + font-size: 18px; + line-height: 1.8; + } + .zen-exit-button { + position: fixed; + bottom: 2rem; + right: 2rem; + padding: 0.75rem 1.25rem; + border-radius: 9999px; + background-color: var(--bg-tertiary); + color: var(--text-secondary); + border: 1px solid var(--border-primary); + cursor: pointer; + opacity: 0; + transition: opacity 0.3s ease, transform 0.2s ease; + z-index: 9999; + font-size: 0.875rem; + display: flex; + align-items: center; + gap: 0.5rem; + } + .zen-exit-button:hover { + opacity: 1 !important; + background-color: var(--bg-secondary); + transform: scale(1.05); + } + .zen-mode-active:hover .zen-exit-button { + opacity: 0.6; + } + + /* Zen mode fade transition */ + .zen-fade-enter { + animation: zenFadeIn 0.3s ease-out; + } + @keyframes zenFadeIn { + from { opacity: 0; } + to { opacity: 1; } + } + /* Syntax highlight colors using theme variables */ .syntax-overlay .md-heading { color: var(--accent-primary); font-weight: 600; } .syntax-overlay .md-bold { color: var(--text-primary); font-weight: 700; } @@ -1000,7 +1061,23 @@ } - + + + +
@@ -1741,9 +1818,9 @@