* design: add tags property type wireframes
Three frames showing the Tags multi-select property:
- Display state: colored pills with X to remove, + button to add
- Input state: dropdown with vault suggestions, checkmarks for selected
- Color picker: per-tag color selection row with accent palette
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add tags (multi-select) property type
Adds a new 'tags' display mode for array-valued frontmatter properties.
Includes TagPill components with deterministic color assignment,
inline tag editing with autocomplete from vault-wide values, and
automatic detection for common tag key patterns (tags, keywords,
categories, labels).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: SearchPanel test — fire ArrowDown on document not window
---------
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* design: relationship-x-cosmetic wireframes
* fix: relationship X button appears inline inside pill on hover
X button now renders as a flex child inside the pill (next to the type icon)
instead of being absolutely positioned outside the pill boundary.
- Pill uses inset ring border on hover when bgColor is set
- X appears inline with type icon via flex layout
- Type icon rendered at 50% opacity per design spec
- Updated test selector: .group/link is now the button element itself
* fix: useRef type for debounce timer (pre-existing build error on main)
---------
Co-authored-by: Test <test@test.com>
When the editor's first block is an H1 heading, the note title
automatically stays in sync. Changes are debounced at 500ms.
Manual rename via tab breaks the sync until the tab is switched.
- Show H1 in editor (stop stripping on load, stop reconstructing on save)
- New useHeadingTitleSync hook tracks sync state and debounces title updates
- handleEditorChange keeps frontmatter title: in sync with H1
- Fast path for H1-only content preserves instant new-note interactivity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- StatusDropdown: change anchor element from <div> to <span> to fix
invalid HTML nesting inside <span> parents. Browsers auto-correct
<div> inside <span> by ripping the element out, breaking
anchorRef.parentElement positioning. JSDOM doesn't auto-correct,
so tests passed but the real app's dropdown failed to position.
- StatusValue: revert shrink-0 back to min-w-0 so the status pill
can truncate in narrow panels instead of overflowing.
- PropertyRow: add min-w-0 and gap-2 for proper flex overflow,
wrap property key in truncate span.
- AddPropertyForm: add flex-wrap, reduce input widths, set
min-w-[60px] on value inputs for narrow panel support.
- InfoRow/TypeSelector/ReadOnlyType: add min-w-0 and gap-2.
- Tests: increase timeout for 3 Radix Select interaction tests
that are slow in JSDOM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract heading-stripping logic into `extractEditorBody` — fixes a bug
where the regex failed to strip the title heading from newly created
notes (because `splitFrontmatter` left a leading newline that the
regex didn't account for).
Add a fast path in `doSwap` for empty body content: when the body is
empty (common case for new notes), skip the potentially-async
`tryParseMarkdownToBlocks` pipeline entirely and apply a single empty
paragraph block synchronously. This eliminates the multi-second delay
caused by BlockNote's async markdown parser initialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The positionDropdown callback ref ran during React's commit phase
before anchorRef was assigned (children refs commit before parents),
so the dropdown was never positioned and the invisible backdrop
stole all subsequent clicks. Switch to useLayoutEffect which runs
after all refs are set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the sidebar is hidden (editor-list view mode), the NoteList becomes
the leftmost panel and its header title overlaps with macOS traffic lights.
Add 80px left padding to the NoteList header when sidebarCollapsed is true,
matching the sidebar title bar's existing traffic light clearance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verified all 115 frames in ui-design.pen render in light mode.
No remaining before-variants, no duplicates found.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use portal-based positioning for property panel dropdowns
StatusDropdown and DisplayModeSelector used absolute positioning
within the Inspector's overflow-hidden container, causing dropdowns
to be clipped when the Properties panel is narrow (200-280px).
Both now render via createPortal into document.body with fixed
positioning calculated from the trigger element's bounding rect.
This matches the pattern used by existing Radix UI components
(Select, Popover) in the codebase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: property dropdown narrow panel fix — before/after frames
---------
Co-authored-by: Laputa App <laputa@app.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Update tab indicator to blue dot (was green), add italic font
style to unsaved tab title, rename frame to match new behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New notes created via Cmd+N now stay in memory until the user
explicitly saves with Cmd+S. This eliminates the disk-write
blocking delay and lets the cursor appear instantly.
- Add 'unsaved' to NoteStatus; blue dot + italic title in tab bar
- useUnsavedTracker in useVaultLoader manages unsaved path set
- useNoteActions skips persist on create, cleans up on close
- useEditorSave accepts unsavedFallback for first-save scenario
- App.tsx wires tracking via contentChangeRef + clearUnsaved
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the first-line-of-content snippet in search results with
a metadata row showing: relative date, created date (when different
from modified), word count, and outgoing link count.
Uses the existing formatSearchSubtitle() helper. Entry lookup now
stores full VaultEntry for metadata access. Graceful degradation
when fields are missing/zero.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two frames showing the redesigned search result subtitle:
- Main view with metadata (date, word count, links) replacing snippet
- States catalog: all metadata, same dates, no links, empty, no date
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Popover and Select components: add collisionPadding=8 as default
- TypeSelector and AddPropertyForm SelectContent: position=popper, side=left
- DateValue and AddDateInput PopoverContent: side=left
Dropdowns now flip direction when hitting viewport edge instead of clipping.
Bug 1: Replace plain-text Radix Select in AddStatusInput with the same
StatusDropdown component used for existing status properties. Both now
show colored pills, search, and custom status creation.
Bug 2: Add color swatch dot next to each status option in the dropdown.
Clicking it opens an inline palette of 8 accent colors that persist via
localStorage (leveraging existing setStatusColor infrastructure).
Refactor StatusDropdown to extract useStatusFiltering, useStatusKeyboard
hooks and VaultSection/SuggestedSection/CreateSection sub-components to
keep Code Health above 9.2 threshold.
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- selectRange() now includes the currently open note as the anchor
- Added setAnchor() to track which note is the selection start
- Added select-none to NoteList to prevent browser text selection on Shift+click
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
BlockNote uses z-index: 11000 for its toolbar/popover elements.
The Radix UI Select and Popover portals used z-50 (z-index: 50),
causing all inspector dropdowns (type selector, property type picker,
date pickers) to render behind the editor. Raised to z-[12000] to
match the existing StatusDropdown and DisplayModeSelector z-index.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add --no-clean to cargo llvm-cov for incremental builds (~5s vs ~8min)
- Skip Rust checks when no src-tauri/ files changed
- Merge redundant frontend test + coverage into single coverage step
- Reorder: fast lints (fmt, clippy) before slow coverage for quick feedback
- Add timing output and LAPUTA_FULL_COVERAGE=1 escape hatch
Expected: frontend-only push ~1 min, frontend+Rust ~2-3 min
All checks now run locally via .husky/pre-push before any push.
This eliminates GitHub Actions queue, runner saturation, and
'waiting for status' blocks entirely.
Hook runs: tsc, Vite build, frontend tests, frontend coverage (≥70%),
Rust coverage (≥85%), Clippy, rustfmt, CodeScene (≥9.2).
Claude Code is explicitly forbidden from using --no-verify (documented
in CLAUDE.md). Branch protection required status checks removed.
Remote CI kept as non-blocking safety net only.
Add color dot indicators to each status option in the dropdown. Clicking
the dot opens an inline palette of 8 accent colors (from the design system).
Color assignments persist in localStorage and override the built-in defaults.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The metadata subtitle (date + word count) from #94 was only intended for
search results. Reverts NoteItem and PinnedCard to show first 2 lines of
note content with a date line underneath.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The TypeSelector on existing properties used a colored pill with no
border, while the add-property form used a bordered muted-bg control.
Align both to the add-property style: 26px height, visible border,
muted background, 4px radius.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* design: search subtitle metadata layout with 2 frames
Frame 1: Search result items with metadata subtitle line showing
modified date, word count, and link count below the snippet.
Frame 2: NoteList items with enhanced subtitle including link count.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add metadata subtitle to search results and note list items
- formatSubtitle now shows link count (e.g. "2h ago · 342 words · 5 links")
- New formatSearchSubtitle shows full metadata in search results:
modified date, created date, word count, and link count
- SearchPanel renders metadata line under each search result snippet
- Mock entries updated with realistic outgoingLinks data
- 11 new tests covering formatSearchSubtitle and search result metadata
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract SearchResultItem and SearchResultsList from SearchContent
Reduces cyclomatic complexity from 24 to manageable levels by
splitting the monolithic SearchContent into three focused components.
Code Health: 8.97 -> 9.23.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>