Skip to content

Commit cbc0983

Browse files
author
Antonio Maiolo
authored
fix(app): fix Notes editor formatting and title issues (#93)
1 parent 466ebd7 commit cbc0983

3 files changed

Lines changed: 120 additions & 80 deletions

File tree

.changeset/fix-notes-editor.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"think-app": patch
3+
---
4+
5+
Fix Notes editor formatting and title wrapping issues
6+
7+
- Fix bullet list, numbered list, and blockquote buttons not working (CSS was being purged by Tailwind)
8+
- Fix H2/H3 heading differentiation (H3 now visually distinct with smaller size and lighter weight)
9+
- Fix title horizontal scrolling (changed to auto-resizing textarea)
10+
- Fix Enter key in title to move focus to editor content

app/src/components/editor/NoteEditor.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function NoteEditor({
6060
const [showCloseWarning, setShowCloseWarning] = useState(false);
6161

6262
// Ref for focus
63-
const titleInputRef = useRef<HTMLInputElement>(null);
63+
const titleInputRef = useRef<HTMLTextAreaElement>(null);
6464
// Track initial content for regeneration check on close
6565
const initialContentRef = useRef("");
6666

@@ -135,6 +135,15 @@ export function NoteEditor({
135135
};
136136
}, [isOpen]);
137137

138+
// Auto-resize title textarea when title changes or editor opens
139+
useEffect(() => {
140+
if (titleInputRef.current && isOpen) {
141+
const textarea = titleInputRef.current;
142+
textarea.style.height = 'auto';
143+
textarea.style.height = textarea.scrollHeight + 'px';
144+
}
145+
}, [title, isOpen]);
146+
138147
// Handle save - triggers regeneration on successful save
139148
const handleSave = useCallback(async () => {
140149
const finalId = await save();
@@ -225,13 +234,24 @@ export function NoteEditor({
225234
<div className="flex-1 overflow-y-auto">
226235
<div className={editorTokens.content}>
227236
{/* Title */}
228-
<input
237+
<textarea
229238
ref={titleInputRef}
230-
type="text"
231239
placeholder="Untitled"
232240
value={title}
233241
onChange={(e) => setTitle(e.target.value)}
234-
className={cn(editorTokens.title, "mb-6")}
242+
rows={1}
243+
className={cn(editorTokens.title, "mb-6 resize-none overflow-hidden")}
244+
onInput={(e) => {
245+
const target = e.target as HTMLTextAreaElement;
246+
target.style.height = 'auto';
247+
target.style.height = target.scrollHeight + 'px';
248+
}}
249+
onKeyDown={(e) => {
250+
if (e.key === 'Enter') {
251+
e.preventDefault();
252+
editor?.chain().focus().run();
253+
}
254+
}}
235255
/>
236256

237257
{/* Editor */}

app/src/index.css

Lines changed: 86 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -185,81 +185,91 @@
185185
.chat-prose blockquote {
186186
@apply border-l-2 border-primary/50 pl-3 italic my-2;
187187
}
188+
}
188189

189-
/* TipTap Editor prose styling */
190-
.ProseMirror {
191-
line-height: 1.7;
192-
letter-spacing: -0.01em;
193-
}
194-
.ProseMirror > * + * {
195-
margin-top: 0.75em;
196-
}
197-
.ProseMirror p {
198-
margin: 0.5em 0;
199-
}
200-
.ProseMirror h1 {
201-
font-family: 'Goudy Bookletter 1911', Georgia, serif;
202-
font-size: 1.875rem;
203-
font-weight: 600;
204-
margin: 1.5rem 0 0.75rem;
205-
line-height: 1.3;
206-
}
207-
.ProseMirror h2 {
208-
font-size: 1.5rem;
209-
font-weight: 600;
210-
margin: 1.25rem 0 0.5rem;
211-
line-height: 1.35;
212-
}
213-
.ProseMirror h3 {
214-
font-size: 1.25rem;
215-
font-weight: 600;
216-
margin: 1rem 0 0.5rem;
217-
line-height: 1.4;
218-
}
219-
.ProseMirror ul {
220-
list-style-type: disc;
221-
padding-left: 1.5em;
222-
margin: 0.5em 0;
223-
}
224-
.ProseMirror ol {
225-
list-style-type: decimal;
226-
padding-left: 1.5em;
227-
margin: 0.5em 0;
228-
}
229-
.ProseMirror li {
230-
margin: 0.25em 0;
231-
}
232-
.ProseMirror li > p {
233-
margin: 0;
234-
}
235-
.ProseMirror blockquote {
236-
border-left: 3px solid hsl(var(--primary));
237-
padding-left: 1rem;
238-
margin: 1rem 0;
239-
color: hsl(var(--muted-foreground));
240-
font-style: italic;
241-
}
242-
.ProseMirror code {
243-
@apply bg-black/10 dark:bg-white/10 px-1.5 py-0.5 rounded text-[0.9em];
244-
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
245-
}
246-
.ProseMirror pre {
247-
@apply bg-black/10 dark:bg-white/10 p-3 rounded-lg overflow-x-auto my-2;
248-
}
249-
.ProseMirror pre code {
250-
@apply bg-transparent p-0;
251-
font-size: 0.875rem;
252-
line-height: 1.6;
253-
}
254-
.ProseMirror a {
255-
@apply text-primary underline;
256-
}
257-
.ProseMirror strong {
258-
font-weight: 600;
259-
}
260-
.ProseMirror hr {
261-
border: none;
262-
border-top: 1px solid hsl(var(--border));
263-
margin: 1.5rem 0;
264-
}
190+
/* TipTap Editor prose styling - OUTSIDE @layer to prevent Tailwind purging */
191+
.ProseMirror {
192+
line-height: 1.7;
193+
letter-spacing: -0.01em;
194+
}
195+
.ProseMirror > * + * {
196+
margin-top: 0.75em;
197+
}
198+
.ProseMirror p {
199+
margin: 0.5em 0;
200+
}
201+
.ProseMirror h1 {
202+
font-family: 'Goudy Bookletter 1911', Georgia, serif;
203+
font-size: 1.875rem;
204+
font-weight: 600;
205+
margin: 1.5rem 0 0.75rem;
206+
line-height: 1.3;
207+
}
208+
.ProseMirror h2 {
209+
font-size: 1.5rem;
210+
font-weight: 600;
211+
margin: 1.25rem 0 0.5rem;
212+
line-height: 1.35;
213+
}
214+
.ProseMirror h3 {
215+
font-size: 1.125rem !important;
216+
font-weight: 500 !important;
217+
margin: 1rem 0 0.5rem;
218+
line-height: 1.4;
219+
}
220+
.ProseMirror ul {
221+
list-style-type: disc !important;
222+
padding-left: 1.5em !important;
223+
margin: 0.5em 0;
224+
}
225+
.ProseMirror ol {
226+
list-style-type: decimal !important;
227+
padding-left: 1.5em !important;
228+
margin: 0.5em 0;
229+
}
230+
.ProseMirror li {
231+
margin: 0.25em 0;
232+
display: list-item !important;
233+
}
234+
.ProseMirror li > p {
235+
margin: 0;
236+
}
237+
.ProseMirror blockquote {
238+
border-left: 3px solid hsl(var(--primary));
239+
padding-left: 1rem;
240+
margin: 1rem 0;
241+
color: hsl(var(--muted-foreground));
242+
font-style: italic;
243+
}
244+
.ProseMirror code {
245+
background-color: rgba(0, 0, 0, 0.1);
246+
padding: 0.125rem 0.375rem;
247+
border-radius: 0.25rem;
248+
font-size: 0.9em;
249+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
250+
}
251+
.ProseMirror pre {
252+
background-color: rgba(0, 0, 0, 0.1);
253+
padding: 0.75rem;
254+
border-radius: 0.5rem;
255+
overflow-x: auto;
256+
margin: 0.5rem 0;
257+
}
258+
.ProseMirror pre code {
259+
background-color: transparent;
260+
padding: 0;
261+
font-size: 0.875rem;
262+
line-height: 1.6;
263+
}
264+
.ProseMirror a {
265+
color: hsl(var(--primary));
266+
text-decoration: underline;
267+
}
268+
.ProseMirror strong {
269+
font-weight: 600;
270+
}
271+
.ProseMirror hr {
272+
border: none;
273+
border-top: 1px solid hsl(var(--border));
274+
margin: 1.5rem 0;
265275
}

0 commit comments

Comments
 (0)