🌿 Collaborative wiki on ATProto lichen.wiki
atproto
14
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix scrolling bar in edit mode

juprodh 97766f93 1eae9c25

+91 -21
+32 -13
public/editor/editor.ts
··· 11 11 function initEditor(root: Document | Element = document): void { 12 12 const textarea = root.querySelector<HTMLTextAreaElement>("textarea#content"); 13 13 if (!textarea) return; 14 - 15 - // Already initialized 16 14 if (textarea.style.display === "none") return; 17 15 18 16 const form = textarea.closest("form"); ··· 28 26 wrapper.style.minHeight = "0"; 29 27 30 28 const editorPane = document.createElement("div"); 31 - editorPane.style.flex = "1"; 29 + editorPane.style.flex = "1 1 0%"; 32 30 editorPane.style.minWidth = "0"; 31 + editorPane.style.minHeight = "0"; 33 32 editorPane.style.overflow = "hidden"; 34 33 editorPane.style.border = `1px solid ${THEME_HEX.paneBorder}`; 35 34 editorPane.style.borderRadius = "0.375rem"; ··· 38 37 39 38 const preview = document.createElement("div"); 40 39 preview.className = "prose max-w-none"; 41 - preview.style.flex = "1"; 40 + preview.style.flex = "1 1 0%"; 42 41 preview.style.minWidth = "0"; 43 42 preview.style.overflow = "auto"; 44 43 preview.style.padding = "0.75rem"; ··· 50 49 wrapper.appendChild(preview); 51 50 textarea.parentElement?.appendChild(wrapper); 52 51 53 - let debounceTimer: ReturnType<typeof setTimeout>; 52 + // --- CRITICAL: Force scrollable editor with CSS --- 53 + const styleId = "lichen-editor-scroll-fix"; 54 + if (!document.getElementById(styleId)) { 55 + const style = document.createElement("style"); 56 + style.id = styleId; 57 + style.textContent = ` 58 + .cm-editor { 59 + height: 100% !important; 60 + flex: 1 1 0% !important; 61 + min-height: 0 !important; 62 + } 63 + .cm-scroller { 64 + overflow-y: auto !important; 65 + flex: 1 1 0% !important; 66 + min-height: 0 !important; 67 + } 68 + `; 69 + document.head.appendChild(style); 70 + } 71 + // ------------------------------------------------ 54 72 55 - // Hidden file input for image uploads 73 + let debounceTimer: ReturnType<typeof setTimeout>; 56 74 const fileInput = document.createElement("input"); 57 75 fileInput.type = "file"; 58 76 fileInput.accept = "image/jpeg,image/png,image/gif,image/webp"; ··· 64 82 extensions: [ 65 83 basicSetup, 66 84 markdown(), 67 - EditorView.theme({ 68 - "&": { flex: "1", display: "flex", flexDirection: "column" }, 69 - ".cm-scroller": { flex: "1", overflow: "auto" }, 70 - }), 71 85 EditorView.lineWrapping, 72 86 EditorView.updateListener.of((update) => { 73 87 if (update.docChanged) { ··· 110 124 111 125 activeView = view; 112 126 113 - // Insert toolbar at top of editor pane (before CodeMirror) 127 + // Also apply inline styles as a fallback 128 + view.dom.style.height = "100%"; 129 + view.dom.style.flex = "1"; 130 + const scroller = view.scrollDOM; 131 + if (scroller) { 132 + scroller.style.overflowY = "auto"; 133 + } 134 + 114 135 const toolbar = createToolbar(view, fileInput); 115 136 editorPane.insertBefore(toolbar, editorPane.firstChild); 116 137 editorPane.appendChild(fileInput); 117 138 118 - // File input handler 119 139 fileInput.addEventListener("change", () => { 120 140 const file = fileInput.files?.[0]; 121 141 if (file) { ··· 125 145 } 126 146 }); 127 147 128 - // Initial preview render 129 148 renderPreview(preview, textarea.value); 130 149 131 150 form.addEventListener("submit", () => {
+36 -7
src/views/edit-note.ts
··· 14 14 const locale = options?.locale ?? "en"; 15 15 const msg = t(locale); 16 16 17 - return layout( 18 - `${msg.wiki.edit} ${noteTitle}`, 19 - ` 20 - <form method="POST" action="/wiki/${wikiSlug}/${noteSlug}/edit" class="flex flex-col gap-4 md:h-[calc(100vh-8rem)] md:overflow-hidden"> 17 + // CSS fix: ensures the edit form has a fixed height on all viewport widths 18 + // so that the CodeMirror editor can constrain its scroller and show a scrollbar. 19 + const scrollFixStyle = ` 20 + <style> 21 + /* Force the edit form to take full viewport height minus top bar */ 22 + .edit-form { 23 + height: calc(100vh - 8rem) !important; 24 + overflow: hidden !important; 25 + } 26 + /* Ensure the editor pane respects the flex container */ 27 + .edit-form .flex-1 { 28 + min-height: 0 !important; 29 + } 30 + /* Make sure CodeMirror's editor and scroller behave */ 31 + .cm-editor { 32 + height: 100% !important; 33 + flex: 1 1 0% !important; 34 + min-height: 0 !important; 35 + } 36 + .cm-scroller { 37 + overflow-y: auto !important; 38 + flex: 1 1 0% !important; 39 + min-height: 0 !important; 40 + } 41 + </style> 42 + `; 43 + 44 + const formHtml = ` 45 + <form method="POST" action="/wiki/${wikiSlug}/${noteSlug}/edit" class="edit-form flex flex-col gap-4"> 21 46 <div class="shrink-0"> 22 47 <label for="title" class="block text-sm font-medium ${THEME.textSecondary} mb-1">${msg.editor.title}</label> 23 48 <input ··· 64 89 </div> 65 90 </form> 66 91 <form id="delete-note-form" method="POST" action="/wiki/${wikiSlug}/${noteSlug}/delete" class="hidden"></form> 67 - `, 68 - { ...options, wikiName, wikiSlug }, 69 - ); 92 + `; 93 + 94 + return layout(`${msg.wiki.edit} ${noteTitle}`, scrollFixStyle + formHtml, { 95 + ...options, 96 + wikiName, 97 + wikiSlug, 98 + }); 70 99 }
+23 -1
src/views/new-note.ts
··· 28 28 const titleValue = escapeHtml(options?.titleValue ?? ""); 29 29 const escapedContent = escapeHtml(options?.contentValue ?? ""); 30 30 31 + // Simple fix: give the editor a max height and make it scroll internally 32 + const scrollFixStyle = ` 33 + <style> 34 + /* Target the CodeMirror editor that replaces the textarea */ 35 + .cm-editor { 36 + max-height: 60vh; 37 + height: auto !important; 38 + overflow: hidden; 39 + } 40 + .cm-scroller { 41 + overflow-y: auto !important; 42 + max-height: 60vh; 43 + } 44 + /* Ensure the textarea wrapper doesn't constrain the editor */ 45 + .flex-1 .cm-editor, 46 + .space-y-4 .cm-editor { 47 + max-height: 60vh; 48 + } 49 + </style> 50 + `; 51 + 31 52 return layout( 32 53 `${msg.wiki.newNote} — ${wikiName}`, 33 - ` 54 + scrollFixStyle + 55 + ` 34 56 <h1 class="text-3xl font-bold ${THEME.textPrimary} mb-6">${msg.wiki.newNote}</h1> 35 57 ${errorHtml} 36 58 <div class="mb-6 pb-4 border-b ${THEME.borderDefault}">