Skip to content

[#912 Slice 3] Breadcrumb navigation + filetree dropdown + search #921

Closed

Description

@jeonghun-jj-lee

Important

Problem — After Slice 2 provides the Finder-style directory navigation, users still lack three key navigation aids: a breadcrumb path bar for jumping to ancestor directories, a filetree dropdown for quick-jumping anywhere, and a search bar for finding files by name across the project.

Approach — Build preview-breadcrumb.tsx with individually clickable path segments and a dropdown trigger that opens a FileTreeV2 (static mode) overlay for files, plus a custom click interceptor for folder navigation. Add a persistent search bar at the top that replaces the directory view with flat substring-matched results. Both the dropdown and search need the full renderable file set, so this slice adds a recursive tree walk + cache on tab mount.

Scope — in: breadcrumb component, filetree dropdown overlay, search bar, recursive file enumeration + cache · out: CodeMirror editor, image/PDF rendering, no-project fallback

Acceptance Criteria

  • Breadcrumb path bar replaces the plain-text path from Slice 2; each segment (e.g. src, components, session) is individually clickable and navigates to that directory
  • A separate dropdown trigger (chevron icon) on the breadcrumb opens an overlay showing the full filtered filetree
  • The dropdown overlay uses FileTreeV2 in static mode (pass allowed={cachedRenderablePaths} to the component, which internally calls buildFileTreeV2Model). File clicks fire via the existing onFileClick prop and navigate to that file.
  • Folder navigation in the dropdown: since FileTreeV2 has no onFolderClick prop (folder clicks toggle expand/collapse), add a click interceptor on [data-slot="file-tree-v2-row"] directory rows that intercepts the click, updates currentPath, and closes the dropdown. The interceptor sits on the dropdown container, not inside FileTreeV2.
  • Clicking outside the dropdown or selecting a file/folder closes it
  • The full renderable file set is obtained by recursively walking file.tree.children on tab mount, filtering with isRenderable() from markdown-utils.ts, and caching the path array
  • The cache refreshes when the tab regains focus
  • A search bar is always visible above the breadcrumb in both directory and file views
  • Typing in the search bar replaces the directory view with a flat substring-matched list of all renderable files (case-insensitive, matching against full relative paths)
  • Clicking a search result opens that file directly
  • Clearing the search bar (or pressing Escape) restores the directory view at whatever folder the user was in
  • Arrow keys navigate the search results list; Enter opens the highlighted result

Testing Decisions

Add unit tests for the recursive file enumeration and cache logic (mock file.tree.children). Test the search filter as a pure function (substring matching against path arrays). Test breadcrumb segment extraction from a path string. Extends Slice 2's navigation state tests for the search-query transitions.

Key Decisions

Recursive walk on tab mount for the dropdown and search. The lazy per-directory approach from Slice 2 works for the Finder view, but the dropdown and search need all renderable paths up front. Walk the tree recursively via repeated file.tree.children calls, filter with isRenderable(), cache the result. Refresh on tab focus to pick up new files.

FileTreeV2 in static mode via allowed prop. Pass the cached path array as the allowed prop to FileTreeV2. The component internally calls buildFileTreeV2Model — the implementing agent does not call the model function directly.

Folder navigation via click interceptor. FileTreeV2 hardcodes folder clicks to toggleDirectory with no onFolderClick prop. Rather than modifying the upstream component, attach a delegated click listener on the dropdown container that intercepts clicks on [data-slot="file-tree-v2-row"] elements with a directory data-path. This navigates to the folder and closes the dropdown while leaving FileTreeV2's expand/collapse intact for browsing.

Search replaces directory view, doesn't overlay it. When the search bar has text, the entire content area below the breadcrumb switches to a flat results list. Same pattern as Files Changed's SessionFileListV2.

Constraints & Invariants

  • The breadcrumb must always reflect the true current directory path — clicking a segment must navigate to exactly that directory
  • The dropdown must show the same filtered set as the search (same cache, same filter)
  • Search must be responsive for the expected file count (dozens to low hundreds of renderable files)
  • isRenderable() from markdown-utils.ts is the single filter — never a local extension list

Prior Art

  • file-tree-v2.tsx + file-tree-v2-model.ts — reused in static mode via allowed prop for the dropdown
  • session-file-list-v2.tsx — pattern for flat search results
  • review-panel-v2.tsx buildCollapsedTree() — pattern for collapsed-path dropdown (though we use FileTreeV2 instead)
  • review-diff-kinds.ts filterReviewFiles() — pattern for substring filtering

Source

Part of #912 · Blocked by #920

Activity

  1. jeonghun-jj-lee commented on Sep 9, 2026

    @jeonghun-jj-lee
    ContributorAuthor

    Superseded by #931 (Preview as sidebar companion). The Finder-based design is replaced by the reactive companion model — sidebar drives file selection, Preview is a pure viewer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

afkImplementable without human interaction

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions