fix(opensidian): unify content model and modernize UI components#1530
Merged
fix(opensidian): unify content model and modernize UI components#1530
Conversation
- Replace raw <input> in CreateDialog and RenameDialog with Input component - Wrap form inputs in Field + FieldLabel for proper form structure - Replace raw <textarea> in ContentEditor with Textarea component - Add lucide-svelte dependency for upcoming icon replacements - Completed spec items 1.1, 1.2, 1.3, 1.4
- Replace ChevronRight, Folder, FolderOpen, File SVGs in TreeNode.svelte - Import lucide-svelte components (File aliased as FileIcon to avoid collision) - Toolbar.svelte has no inline SVGs, no changes needed - Completed spec items 2.1, 2.2, 2.3, 2.4, 2.5
- Wrap all Toolbar buttons in Tooltip.Root with descriptive content - Add Tooltip.Provider for shared delay settings - Replace manual empty state in FileTree with Empty component - Completed spec items 3.1, 3.2
- Update spec status to Implemented - Check off all success criteria - Add review section with per-file change summary - Note deferred item (3.3 Kbd hints) and follow-up work
…extras Install tree-view component via jsrepo and wrap it in a new FileTreeItem component that preserves all existing behavior—selection state, context menus, CRUD dialogs, keyboard handlers, and accessibility roles. The installed tree-view-folder was customized to forward onOpenChange to bits-ui's Collapsible.Root for controlled expansion state, and to accept a style prop for depth-based padding indentation.
The {#key} block in ContentPanel destroys ContentEditor when
activeFileId changes. DOM removal doesn't fire blur events, so
unsaved edits were silently lost. The $effect cleanup function
now persists dirty content before the component is torn down.
…dle) Two incompatible content stores coexist in document Y.Docs—the timeline array (packages/filesystem) and raw Y.Text (handle API). Writes through one are invisible to the other. Spec proposes making timeline the single source of truth.
A tree view root is always semantically a tree—consumers shouldn't need to remember to pass role="tree" every time.
The upstream tree-view-folder uses CSS nesting (border-l + mx-2) to handle indentation automatically through composition—each nested Folder adds its own margin. This eliminates the need for a depth prop, manual padding-left, and the style prop customization we added.
Folders showed chevron + folder icon + name (3 elements) while files showed icon + name (2 elements), causing misalignment. The chevron already indicates expandability—the separate folder icon is redundant. Matches Obsidian's approach where the chevron is the only folder indicator.
Remove the custom icon snippet from TreeView.Folder so the upstream FolderIcon/FolderOpenIcon defaults render instead. This aligns folder and file rows to the same [icon] + [name] pattern with no chevron.
… to document binding spec Complete the draft spec with resolved open questions, Phase 2 (makeHandle timeline unification), Phase 3 (fuji/honeycrisp migration), anti-pattern reference, and success criteria. Add content model note to the document binding migration spec marking the dual-path decision as superseded.
…w Y.Text
Switch readContent/writeContent from handle.read()/handle.write() (which
use Y.Text('content')) to fs.content.read()/fs.content.write() (which use
the timeline Y.Array). This ensures content written by fs.writeFile() is
visible to the editor and vice versa.
… READMEs
Update workspace-api skill, yjs skill, DocumentHandle JSDoc, workspace
READMEs, and AGENTS.md files to document that handle.read()/write() and
handle.ydoc.getText('content') are anti-patterns. Recommend fs.content
or createTimeline(ydoc) from @epicenter/filesystem instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Opensidian's content editor was silently writing to a store nothing else reads. Meanwhile, the UI was built with raw HTML inputs and inline SVGs instead of shared components. This PR fixes both.
Content model unification
Document Y.Docs had two independent content stores—
Y.Text('content')(used byhandle.read()/write()) andY.Array('timeline')(used byfs.writeFile()/readFile()). Content written through the editor was invisible to the filesystem API and vice versa.This is Phase 1 of the unification spec (
specs/20260313T224500-unify-document-content-model.md). Phase 2 will promote the timeline intopackages/workspacesohandle.read()/write()itself becomes timeline-backed—making both paths equivalent.Documentation updated across skills, READMEs, and JSDoc to mark
handle.read()/write()andhandle.ydoc.getText('content')as anti-patterns until Phase 2 lands.UI modernization
Replaced raw HTML and custom components with shared
@epicenter/uiprimitives andshadcn-svelte-extras:The custom
TreeNode.sveltecomponent was replaced with the upstreamtree-viewpackage, which provides proper ARIA roles, keyboard navigation, and tree-line nesting out of the box. Several follow-up fixes resolved folder icons, chevrons, and a malformed closing tag.Also fixed a content persistence bug: dirty content now saves on component destroy, not just blur—preventing data loss when switching files via the tree view.
Changelog