From da5117477735bebe03b4fbb081aba6f6b0d5e6c6 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Fri, 3 Apr 2026 19:33:52 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20note=20path=20below=20title=20=E2=80=94?= =?UTF-8?q?=20show=20only=20on=20focus,=20remove=20duplicate=20filename?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs fixed in TitleField: 1. Vault-relative path was always visible for subdirectory notes. Now only appears when the title input is focused, hidden on blur. 2. Both bare filename and vault-relative path rendered simultaneously. Now the filename hint is suppressed when the path is visible, so only one line shows (e.g. `docs/adr/0001-tauri-stack`). Also strips the .md extension from the displayed path. Root-level notes continue to show no path (unchanged). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/TitleField.test.tsx | 23 ++++++++++++++++++++--- src/components/TitleField.tsx | 15 ++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/components/TitleField.test.tsx b/src/components/TitleField.test.tsx index 0121ff76..8299d285 100644 --- a/src/components/TitleField.test.tsx +++ b/src/components/TitleField.test.tsx @@ -117,18 +117,35 @@ describe('TitleField', () => { expect(input).toHaveValue('Untitled note') }) - it('shows vault-relative path for notes in subdirectories', () => { + it('shows vault-relative path (without .md) only when title is focused', () => { render( {}} />) - expect(screen.getByTestId('title-field-path')).toHaveTextContent('docs/adr/0001-tauri-stack.md') + // Path hidden by default + expect(screen.queryByTestId('title-field-path')).not.toBeInTheDocument() + // Focus title → path appears + fireEvent.focus(screen.getByTestId('title-field-input')) + expect(screen.getByTestId('title-field-path')).toHaveTextContent('docs/adr/0001-tauri-stack') + // No bare filename shown when path is visible + expect(screen.queryByTestId('title-field-filename')).not.toBeInTheDocument() }) - it('hides path for notes at vault root', () => { + it('hides path on blur', () => { + render( {}} />) + const input = screen.getByTestId('title-field-input') + fireEvent.focus(input) + expect(screen.getByTestId('title-field-path')).toBeInTheDocument() + fireEvent.blur(input) + expect(screen.queryByTestId('title-field-path')).not.toBeInTheDocument() + }) + + it('hides path for notes at vault root even when focused', () => { render( {}} />) + fireEvent.focus(screen.getByTestId('title-field-input')) expect(screen.queryByTestId('title-field-path')).not.toBeInTheDocument() }) it('hides path when vaultPath is not provided', () => { render( {}} />) + fireEvent.focus(screen.getByTestId('title-field-input')) expect(screen.queryByTestId('title-field-path')).not.toBeInTheDocument() }) }) diff --git a/src/components/TitleField.tsx b/src/components/TitleField.tsx index 8e41d046..6b500446 100644 --- a/src/components/TitleField.tsx +++ b/src/components/TitleField.tsx @@ -63,6 +63,7 @@ function useOptimisticTitle(title: string, onTitleChange: (t: string) => void) { */ export function TitleField({ title, filename, editable = true, notePath, vaultPath, onTitleChange }: TitleFieldProps) { const inputRef = useRef(null) + const [isFocused, setIsFocused] = useState(false) const { value, isEditing, handleFocus, commitTitle, revert, setEdit } = useOptimisticTitle(title, onTitleChange) @@ -91,13 +92,17 @@ export function TitleField({ title, filename, editable = true, notePath, vaultPa const expectedSlug = slugify(value.trim() || title) const currentStem = filename.replace(/\.md$/, '') - const showFilename = isEditing || currentStem !== expectedSlug // Compute vault-relative path (only for notes in subdirectories) const relativePath = notePath && vaultPath - ? notePath.replace(vaultPath + '/', '') + ? notePath.replace(vaultPath + '/', '').replace(/\.md$/, '') : null - const showRelativePath = relativePath && relativePath.includes('/') + const isSubdirectory = relativePath != null && relativePath.includes('/') + + // Show path only when title is focused and note is in a subdirectory + const showRelativePath = isFocused && isSubdirectory + // Show filename hint when slug differs, but suppress when path is already visible + const showFilename = !showRelativePath && (isEditing || currentStem !== expectedSlug) return (
@@ -106,8 +111,8 @@ export function TitleField({ title, filename, editable = true, notePath, vaultPa className="title-field__input" value={value} onChange={e => setEdit(e.target.value)} - onFocus={handleFocus} - onBlur={commitTitle} + onFocus={() => { setIsFocused(true); handleFocus() }} + onBlur={() => { setIsFocused(false); commitTitle() }} onKeyDown={handleKeyDown} disabled={!editable} placeholder="Untitled"