From 90af978d0b3476d1c5a53e79458ba7b23c512c38 Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Sat, 28 Mar 2026 16:04:36 -0700 Subject: [PATCH 1/3] fix: print as PDF renders blank page Two issues caused Print as PDF to produce a blank page: 1. The editor scroll container uses absolute positioning (absolute inset-0) which collapses to zero height when print styles set the parent to height: auto. Fixed by adding data-editor-content-area and data-editor-scroll attributes and overriding to position: static in the print media query. 2. The sidebar-hiding rule (#root > div > div:first-child) also hid the entire editor in preview mode (files opened directly in Scratch), where the editor is the first child. Fixed by targeting a [data-sidebar] attribute instead of :first-child. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/App.css | 18 ++++++++++++++++-- src/App.tsx | 1 + src/components/editor/Editor.tsx | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/App.css b/src/App.css index 443c27ec..b6e36ce8 100644 --- a/src/App.css +++ b/src/App.css @@ -1060,8 +1060,8 @@ table.not-prose th { padding: 0 !important; } - /* Hide sidebar - target the first flex child that contains Sidebar */ - #root > div > div:first-child { + /* Hide sidebar when printing */ + [data-sidebar] { display: none !important; } @@ -1109,6 +1109,20 @@ table.not-prose th { height: auto !important; } + /* The editor content area and scroll container use absolute positioning + which collapses to zero height in print. Switch to static flow. */ + [data-editor-content-area] { + position: static !important; + overflow: visible !important; + height: auto !important; + } + + [data-editor-scroll] { + position: static !important; + overflow: visible !important; + height: auto !important; + } + /* Make editor full width for printing */ .ProseMirror { max-width: 100% !important; diff --git a/src/App.tsx b/src/App.tsx index 4a60c2ef..ec802c4f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -454,6 +454,7 @@ function AppContent() { ) : ( <>
diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx index 565f8710..909c2fc0 100644 --- a/src/components/editor/Editor.tsx +++ b/src/components/editor/Editor.tsx @@ -2100,11 +2100,12 @@ export function Editor({
{/* Editor content area with resize handles overlay */} -
+
{!focusMode && !sourceMode && ( )}
Date: Sat, 28 Mar 2026 18:42:30 -0700 Subject: [PATCH 2/3] fix: improve print margins, add Cmd+P shortcut, fix preview mode - Add @page margin (0.75in) for proper PDF margins and override editor padding (pt-8/pb-24/px-6) in print CSS to prevent stacking - Content exceeding printable area: add width constraints on containers, table-layout: fixed, and overflow-wrap: break-word - Allow lists (ul/ol) to break across pages to avoid large whitespace gaps - Hide format bar and toolbar via data attributes instead of fragile :has() selector that Tailwind v4 purges during build - Add Cmd+P keyboard shortcut for print (standard shortcut), move command palette to Cmd+Shift+P - Cmd+P and print menu work in both library notes and preview mode (files opened directly) - Show toast before print dialog noting preview margin quirk (WebKit renders @page margins differently in preview vs actual output); dismiss toast immediately when dialog closes Co-Authored-By: Claude Opus 4.6 (1M context) --- src/App.css | 44 ++++++++++++--------------- src/App.tsx | 11 +++++-- src/components/editor/Editor.tsx | 10 ++++-- src/components/preview/PreviewApp.tsx | 7 +++++ src/services/pdf.ts | 18 +++++++++-- 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/App.css b/src/App.css index b6e36ce8..ea60d3ff 100644 --- a/src/App.css +++ b/src/App.css @@ -1018,6 +1018,10 @@ table.not-prose th { } /* Print styles for clean PDF export */ +@page { + margin: 0.75in; +} + @media print { /* Disable all transitions to prevent color flashing after print */ *, @@ -1050,6 +1054,8 @@ table.not-prose th { height: auto !important; overflow: visible !important; max-height: none !important; + width: 100% !important; + max-width: 100% !important; border: none !important; border-top: none !important; border-bottom: none !important; @@ -1081,26 +1087,10 @@ table.not-prose th { display: none !important; } - /* Hide the toolbar div with drag region */ - [data-tauri-drag-region] { - display: none !important; - visibility: hidden !important; - opacity: 0 !important; - height: 0 !important; - max-height: 0 !important; - margin: 0 !important; - padding: 0 !important; - position: absolute !important; - pointer-events: none !important; - overflow: hidden !important; - } - - /* Hide format bar by targeting its wrapper */ - .flex-1 > div:has(> div[class*="border-b"]) { + /* Hide toolbar and format bar when printing */ + [data-tauri-drag-region], + [data-format-bar] { display: none !important; - height: 0 !important; - max-height: 0 !important; - overflow: hidden !important; } /* Make editor container expand for printing */ @@ -1123,20 +1113,23 @@ table.not-prose th { height: auto !important; } - /* Make editor full width for printing */ + /* Make editor full width for printing and remove editor padding */ .ProseMirror { max-width: 100% !important; padding: 0 !important; margin: 0 !important; overflow: visible !important; height: auto !important; + overflow-wrap: break-word !important; + word-break: break-word !important; } - /* Add padding to prose content for proper margins */ .prose { max-width: 100% !important; - padding: 0.75in 1in !important; + padding: 0 !important; margin: 0 !important; + overflow-wrap: break-word !important; + word-break: break-word !important; } /* Ensure page breaks work well */ @@ -1153,8 +1146,6 @@ table.not-prose th { p, blockquote, pre, - ul, - ol, table { page-break-inside: avoid; break-inside: avoid; @@ -1210,6 +1201,11 @@ table.not-prose th { table { border: 1px solid #d0d0d0 !important; border-collapse: collapse !important; + width: 100% !important; + max-width: 100% !important; + table-layout: fixed !important; + overflow-wrap: break-word !important; + word-break: break-word !important; } th, diff --git a/src/App.tsx b/src/App.tsx index ec802c4f..45a6f90c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -276,13 +276,20 @@ function AppContent() { return; } - // Cmd+P - Open command palette - if ((e.metaKey || e.ctrlKey) && e.key === "p") { + // Cmd+Shift+P - Open command palette + if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "p") { e.preventDefault(); setPaletteOpen(true); return; } + // Cmd+P - Print + if ((e.metaKey || e.ctrlKey) && e.key === "p") { + e.preventDefault(); + window.dispatchEvent(new CustomEvent("print-note")); + return; + } + // Cmd/Ctrl+Shift+F - Open sidebar search if ( (e.metaKey || e.ctrlKey) && diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx index 909c2fc0..d7a4b619 100644 --- a/src/components/editor/Editor.tsx +++ b/src/components/editor/Editor.tsx @@ -1736,14 +1736,19 @@ export function Editor({ if (!editor || !currentNote) return; try { await downloadPdf(editor, currentNote.title); - // Note: window.print() opens the print dialog but doesn't wait for user action - // No success toast needed - the print dialog provides its own feedback } catch (error) { console.error("Failed to open print dialog:", error); toast.error("Failed to open print dialog"); } }, [editor, currentNote]); + // Listen for Cmd+P print shortcut + useEffect(() => { + const handler = () => handleDownloadPdf(); + window.addEventListener("print-note", handler); + return () => window.removeEventListener("print-note", handler); + }, [handleDownloadPdf]); + const handleDownloadMarkdown = useCallback(async () => { if (!editor || !currentNote) return; try { @@ -2089,6 +2094,7 @@ export function Editor({ {/* Format Bar – transition only after initial mount to avoid height animation on note load */}
{ if (!editor) throw new Error("Editor not available"); - // Trigger native print dialog - // The user can choose "Save as PDF" in the print dialog + // Show toast before print dialog. window.print() is synchronous and blocks + // the main thread, so we need a short delay for the toast to render first. + toast("Print preview margins may differ from actual output", { + id: "print-hint", + duration: 4000, + }); + + await new Promise((r) => setTimeout(r, 150)); + + // @page margin handles page margins. The static print CSS in App.css + // sets .ProseMirror { padding: 0 !important } to zero out the editor's + // pt-8/pb-24/px-6 utility padding so it doesn't stack with @page margins. window.print(); + + // Dismiss toast immediately when dialog closes + toast.dismiss("print-hint"); } /** From 77d29636a911d96c357a4d659d8ebc2cc8373bbd Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Sat, 28 Mar 2026 23:48:28 -0700 Subject: [PATCH 3/3] fix: swap Cmd+P/Cmd+Shift+P shortcuts and add print to shortcuts reference Cmd+P now opens the command palette (more standard), Cmd+Shift+P triggers print. Also blocks the browser print dialog in preview mode and adds the print shortcut to the Settings > Shortcuts reference. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/App.tsx | 8 ++++---- src/components/preview/PreviewApp.tsx | 10 ++++++++-- src/components/settings/ShortcutsSettingsSection.tsx | 5 +++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 45a6f90c..46f0edc0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -276,15 +276,15 @@ function AppContent() { return; } - // Cmd+Shift+P - Open command palette - if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "p") { + // Cmd+P - Open command palette + if ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.key === "p") { e.preventDefault(); setPaletteOpen(true); return; } - // Cmd+P - Print - if ((e.metaKey || e.ctrlKey) && e.key === "p") { + // Cmd+Shift+P - Print + if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "p") { e.preventDefault(); window.dispatchEvent(new CustomEvent("print-note")); return; diff --git a/src/components/preview/PreviewApp.tsx b/src/components/preview/PreviewApp.tsx index 27a883c0..73bb8e53 100644 --- a/src/components/preview/PreviewApp.tsx +++ b/src/components/preview/PreviewApp.tsx @@ -113,13 +113,19 @@ export function PreviewApp({ filePath }: PreviewAppProps) { return; } - // Cmd+P: Print - if (modKey && !e.shiftKey && e.key === "p") { + // Cmd+Shift+P: Print + if (modKey && e.shiftKey && e.key.toLowerCase() === "p") { e.preventDefault(); window.dispatchEvent(new CustomEvent("print-note")); return; } + // Cmd+P: Block browser print dialog + if (modKey && !e.shiftKey && e.key === "p") { + e.preventDefault(); + return; + } + // Cmd+R: Reload file from disk if (modKey && e.key === "r") { e.preventDefault(); diff --git a/src/components/settings/ShortcutsSettingsSection.tsx b/src/components/settings/ShortcutsSettingsSection.tsx index fde7c7a4..eb29a3bd 100644 --- a/src/components/settings/ShortcutsSettingsSection.tsx +++ b/src/components/settings/ShortcutsSettingsSection.tsx @@ -62,6 +62,11 @@ const shortcuts: Shortcut[] = [ description: "Open Copy & Export menu", category: "Editor", }, + { + keys: [mod, "Shift", "P"], + description: "Print / Export as PDF", + category: "Editor", + }, { keys: [mod, "F"], description: "Find in current note",