From 07e12b92d02ef5ef733636cc864a1443f887b87d Mon Sep 17 00:00:00 2001
From: Charan Rathore <180254320+charan-rathore@users.noreply.github.com>
Date: Sun, 4 Oct 2026 19:38:06 +0530
Subject: [PATCH 1/2] fix: let long page titles wrap in the page editor
The page title was a single-line input, so long titles were clipped at the right edge. Use an auto-growing textarea that wraps and strips pasted line breaks.
---
src/client/PageDocument.tsx | 11 +++------
src/client/editor.css | 5 ++++
src/client/editor/PageTitleField.tsx | 36 ++++++++++++++++++++++++++++
tests/page-title-field.test.tsx | 25 +++++++++++++++++++
4 files changed, 69 insertions(+), 8 deletions(-)
create mode 100644 src/client/editor/PageTitleField.tsx
create mode 100644 tests/page-title-field.test.tsx
diff --git a/src/client/PageDocument.tsx b/src/client/PageDocument.tsx
index 164b3bf8..da3e1045 100644
--- a/src/client/PageDocument.tsx
+++ b/src/client/PageDocument.tsx
@@ -19,6 +19,7 @@ import { api } from './api';
import { usePageAutosave } from './editor/use-page-autosave';
import { inspectMarkdown } from './editor/markdown';
import { DocumentMenu } from './editor/DocumentMenu';
+import { PageTitleField } from './editor/PageTitleField';
import { PageConversation } from './PageConversation';
const RichEditor = lazy(() => import('./editor/RichEditor'));
export function PageDocument({
@@ -260,15 +261,9 @@ export function PageDocument({
)}
-
- controller.edit({ title: event.target.value })
- }
+ onChange={(title) => controller.edit({ title })}
/>
{sourceMode ? (
<>
diff --git a/src/client/editor.css b/src/client/editor.css
index 9c9c91af..1c630149 100644
--- a/src/client/editor.css
+++ b/src/client/editor.css
@@ -397,6 +397,11 @@
margin-bottom: 24px;
outline: none;
border-radius: 0;
+ display: block;
+ resize: none;
+ overflow: hidden;
+ font-family: inherit;
+ overflow-wrap: anywhere;
}
.document-title::placeholder {
color: #747c70;
diff --git a/src/client/editor/PageTitleField.tsx b/src/client/editor/PageTitleField.tsx
new file mode 100644
index 00000000..e840cc1b
--- /dev/null
+++ b/src/client/editor/PageTitleField.tsx
@@ -0,0 +1,36 @@
+import { useLayoutEffect, useRef } from 'react';
+
+export function singleLineTitle(value: string): string {
+ return value.replace(/[\r\n]+/g, ' ');
+}
+
+export function PageTitleField({
+ value,
+ onChange,
+}: {
+ value: string;
+ onChange: (title: string) => void;
+}) {
+ const ref = useRef(null);
+ useLayoutEffect(() => {
+ const el = ref.current;
+ if (!el) return;
+ el.style.height = 'auto';
+ el.style.height = `${el.scrollHeight}px`;
+ }, [value]);
+ return (
+