Tests verify:
- Trash button shows for non-trashed notes
- Restore button shows for trashed notes
- onClick callbacks fire correctly for both
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added trash icon button in breadcrumb bar for non-trashed notes
- Added restore (arrow counter-clockwise) button for trashed notes
- Trash button sets trashed=true and trashed_at in frontmatter
- Restore button removes trashed/trashed_at from frontmatter
- Added Cmd+Delete keyboard shortcut to trash active note
- Wired handlers through Editor -> App with vault entry updates
- Toast notifications for trash/restore actions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All MOCK_ENTRIES now have realistic createdAt timestamps (always before
modifiedAt). Stock Screener status changed to 'Paused' for sort-by-status
testing variety.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests for getSortComparator (6 tests):
- Sort by modified date descending
- Sort by created date descending (with fallback)
- Sort by title alphabetically
- Sort by status with priority ordering
- Status sort with modified-date tiebreaker
Tests for NoteList sort controls (6 tests):
- Sort button visible in flat list header
- Sort dropdown per relationship subsection
- Sort menu opens with all options
- Sort order changes on option selection
- Menu closes after selection
- Relationship subsection sorting works
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each relationship subsection header now has a sort dropdown control
(ArrowsDownUp icon + current sort label). Users can choose to sort by:
- Modified date (default, newest first)
- Created date (newest first)
- Title (alphabetical A-Z)
- Status (Active > Paused > Done > Finished)
The sort control also appears in the main note list header for flat
list views. Sort preferences are persisted per group in localStorage.
Also updates mock data with varied createdAt/status values for testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add unit test verifying content blocks are applied via deferred microtask
(not synchronously in useEffect). Convert debug E2E test into a proper
regression test that checks editor content appears after clicking a note
and no flushSync errors are logged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added filterEntries tests: trash excluded from all/section/topic/archived,
trash filter returns only trashed entries
- Added NoteList render tests: trash header, TRASHED badge, 30-day warning
banner, empty trash state
- Updated all test files with trashed/trashedAt fields on VaultEntry mocks
- Updated useNoteActions to include trashed/trashedAt on new entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sidebar: replaced disabled Trash placeholder with active filter showing
count badge and destructive color when selected
- Sidebar: trashed notes excluded from section groups and All Notes count
- NoteList: trash filter shows only trashed entries with TRASHED badge
- NoteList: 30-day warning banner when expired trash notes exist
- NoteList: per-note warning text for notes past 30-day retention
- Inspector: trash icon shown before name in relationship pills for
trashed entries, with (trashed) label and dimmed styling
- Inspector: backlinks show trash icon for trashed entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added trashed (boolean) and trashedAt (timestamp) to TypeScript VaultEntry
- Added 'trash' filter to SidebarSelection union type
- Added trashed/trashed_at fields to Rust VaultEntry struct and Frontmatter parser
- Added 3 trashed mock entries for visual testing (recently trashed,
30+ days old, and dropped experiment)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests cover:
- Customize button renders
- Popover opens with toggles for all sections
- Hiding a section removes it and its items from sidebar
- Re-showing a section restores it
- Persistence to/from localStorage
- Hidden sections don't affect top nav (All Notes, Favorites)
- Popover closes on outside click
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a "Customize sections" button above section groups in the sidebar.
Clicking it opens a popover with per-type toggle switches. Hidden sections
disappear from the sidebar entirely but notes remain accessible via
All Notes and search. Visibility state is persisted in localStorage.
- New useSectionVisibility hook: manages hidden sections set in localStorage
- Sidebar: "Customize sections" button + popover with toggle UI
- Outside-click closes the popover
- allSectionGroups (built-in + custom) filtered by visibility before render
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Archive filter in sidebar with count badge
- Hide archived notes from section groups and All Notes count
- Exclude archived notes from sectionGroup and topic filtering
- Show (archived) indicator on relationship chips and backlinks
- Show ARCHIVED badge on note list items
- Display 'Archive' header in NoteList when filter is active
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add archived field to both TypeScript VaultEntry interface and Rust
VaultEntry struct. Parse Archived frontmatter field in Rust backend.
Add archived mock entries (Website Redesign, Twitter Thread Experiment)
for visual testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace vertical EditableList with horizontal TagPillList component.
Array property values now render as inline pill chips with hover X
to remove and a + button to add new items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add TypeCustomizePopover component with color swatches (6 accent colors)
and icon grid (35 curated Phosphor icons)
- Add right-click context menu on sidebar section group headers with
"Customize icon & color…" option
- Sidebar renders custom icons/colors from type entry frontmatter
- NoteList uses custom icons/colors for type badges and pinned cards
- Wire up onCustomizeType in App.tsx to update type frontmatter
- Add updateEntry to useVaultLoader for instant in-memory updates
- Add --accent-orange-light CSS variable
- typeColors utility now accepts optional custom color key overrides
Product decision: Built-in types can also be customized (override their
defaults), not just custom types. The picker is a simple popover that
appears after right-click → "Customize icon & color…".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add icon (string|null) and color (string|null) to VaultEntry interface
- Update Rust VaultEntry struct and frontmatter parsing to read icon/color
- Add icon/color to SKIP_KEYS so they don't appear as relationships
- Set mock data: Recipe type → cooking-pot/orange, Book type → book-open/green
- Update all test files with the new required fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the inspector panel is collapsed, the SlidersHorizontal icon now
appears inline with the other BreadcrumbBar toolbar icons (search, diff,
cursor, AI, more) with no visual separator. The collapsed Inspector
sidebar is no longer rendered — clicking the toolbar icon reopens it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Blob URLs are session-scoped and don't survive page reloads — images
would break on Cmd+Shift+R. Now uploadFile awaits save_image (which
persists to vault/attachments/) and returns a convertFileSrc asset URL
that the Tauri webview can resolve indefinitely.
- Editor.tsx: await save_image → convertFileSrc for Tauri mode;
FileReader.readAsDataURL fallback for browser dev mode
- tauri.conf.json: enable assetProtocol with scope ["**"]
- mock-tauri.ts: save_image returns a plausible file path
- E2E test: expect data: URLs in browser dev mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added non-wikilink array properties (tags, tools, domains) to mock
frontmatter content so the upcoming tag-pill UI has realistic test data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The uploadFile callback was converting images to data URLs via FileReader,
which caused images to get stuck on "Loading..." in the editor. Switched
to URL.createObjectURL() which returns a lightweight blob URL immediately.
The Tauri vault-save path is now fully fire-and-forget so it never blocks
the URL return.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tab navigation: Cmd+Option+Left/Right (Tauri), Cmd+Shift+Left/Right (browser)
- Note list navigation: Cmd+Option+Up/Down moves through visible notes
- Navigating notes replaces the current tab content (no new tab opened)
- Wraps around at list boundaries
- New useKeyboardNavigation hook detects Tauri vs browser environment
- Extracted loadNoteContent and replaceTabWithEntry helpers to reduce
complexity in useNoteActions
- Exported filterEntries, sortByModified, buildRelationshipGroups from
NoteList for reuse in keyboard navigation
Note: useNoteActions (30→31 CC) and App (143→153 LOC) show minimal
degradation on pre-existing code health issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The editor's useCreateBlockNote was missing the uploadFile callback,
so BlockNote had no handler for image uploads (drag-drop, paste, or
toolbar button). Images now convert to data URLs for immediate display.
In Tauri mode, uploaded images are also persisted to the vault's
attachments/ directory via a new save_image backend command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Core implementation:
- CreateTypeDialog: simple dialog with name field for creating new types
- handleCreateType in useNoteActions: creates Type documents in type/ folder
- Dynamic sidebar sections: custom types (Recipe, Book, etc.) appear as new
sidebar sections after built-in ones, each with a + button for instances
- Updated CreateNoteDialog: accepts custom types, shows them with blue accent
- handleCreateNote now supports custom types (folder = lowercased type name)
Product decisions:
- The + on Types section opens CreateTypeDialog (not CreateNoteDialog)
- Custom type sections use FileText icon and blue accent color by default
- Section labels are pluralized (e.g., "Recipes", "Books")
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The BlockNote editor container (.bn-container) had no explicit width,
so it sized based on content. With short or empty document titles,
the editor collapsed to a very small width.
Fix: set width: 100% on .bn-container and .bn-editor so the editor
always fills available space. Added margin: 0 auto on .bn-editor to
keep the 760px text column centered.
Also adds an E2E test verifying editor width stays above 300px.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add mock data for two user-created types (Recipe, Book) plus example
instances (Pasta Carbonara, Designing Data-Intensive Applications).
This enables testing the create-new-types feature in the browser.
Also fix pre-existing test: Sidebar.test expected 7 section groups
but there are 8 (Types was added but test count wasn't updated).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Test that + buttons render for all 7 section groups
- Test that clicking + calls onCreateType with correct type
- Test that + buttons are hidden when callback not provided
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each sidebar section header (Projects, People, Topics, etc.) now shows
a + button on hover. Clicking it opens the CreateNoteDialog pre-filled
with that section's type, so users can quickly create new items without
manually selecting the type.
- Add defaultType prop to CreateNoteDialog for pre-selecting type
- Add onCreateType callback to Sidebar with hover-visible + button
- Wire up in App.tsx with unified openCreateDialog handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Accept string | null in typeColors functions (matches VaultEntry.isA type)
- Add missing snippet/relationships fields to test mock entries
- Remove unused imports (AIChatPanel in App, cn in Editor)
- Fix Promise type cast in Editor.tsx tryParseMarkdownToBlocks
- Fix null coalescing in Inspector resolveRefType return
- Remove unused container variable in NoteList test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Type is a special relationship handled separately by the sidebar,
so it should not appear as one of the generic relationship groups
in the note list entity view. Added case-insensitive filter to
exclude the "type" key from the otherKeys loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>