Repository navigation
How the Navigation Bar Works
This chapter explains how the path above the code became a Navigation Bar: crumbs with a popup per folder, keyboard moves through them, and a search in each list. The user side is in Navigation Bar.
The path bar used to show the crumbs as plain text, so opening a neighbor file meant the mouse and the Files panel. People move around a project with Cmd+Up and the arrow keys, and the user asked for the same.
flowchart TD
Key["Cmd+Up / Alt+Home, Edit menu, or the editor keymap"] --> Run["runWorkspaceShortcut: navigationBar"]
Run --> Open["openNavigationBar (workspaceActions.ts)"]
Open --> Jump["navBarStore.jump()"]
Jump -->|"a path bar claimed it"| Inline["NavigationBar in FileView or EmptyMain"]
Jump -->|"no file on screen"| Floating["floating NavigationBar in Workspace.svelte"]
Inline --> Popup["popup: api.listDirectories, navRows"]
Floating --> Popup
Popup -->|file| OpenFile["navigation.openFileAt"]
Popup -->|"no match"| Search["Search Everywhere: Files"]
NavigationBar.svelte draws the crumbs (the library's Breadcrumbs) from crumbsFor in navBarModel.ts: a workspace crumb when there are several folders, the workspace folder, each folder down the path, and the file. The farthest crumb gets the largest flex-shrink, so the file name stays readable longest.
Several bars can be mounted at once (one per tab, two editor groups, the welcome screen). The one that should answer the key gets claimed and calls navBarStore.claim(owner) with its own Symbol. navBarStore.jump() remembers the focused element, then either makes that bar active and bumps jumpToken, or sets floating. The active bar's effect sees the new token and opens its popup on startIndex: the file's folder, so the list shows the file's neighbors with the file selected.
navBarStore.active is the one bar that has the keyboard; any other bar resets itself. close(restore) puts the focus back, except after a click elsewhere or opening a file.
The fileToolbar setting (Settings > Appearance > File toolbar: "top", "bottom" or "none" shown as Hidden) and its fileToolbarBreadcrumbs switch decide which bars exist, and so which one claims the jump:
| Placement | Bars mounted | Cmd+Up goes to |
|---|---|---|
| Top |
FileView's path bar, the welcome screen's strip (EmptyMain.svelte) |
The claimed one; on the Log or a diff, the floating bar |
| Bottom | The same as Top, but FileView draws its whole bar (FileBar.svelte) under the code, and the welcome screen's strip goes to its foot |
The claimed one; on the Log or a diff, the floating bar |
| Hidden, or the Breadcrumbs switch off | None | The floating bar |
The floating bar points at navTarget(): the file on screen in the focused group, else the active repository. floatingAnchor() puts it at the top left of .editor-group.focused when the bar is hidden. place() opens a popup upward when there is under 200 px below the crumb, as in a bar under the code.
Moving through popups builds a trail of crumbs that may leave the file's path. The model keeps the rules pure:
-
listedIndex: the crumb whose contents a popup lists. A file lists its own folder. -
selectedPathFor: the entry to select, which is the next crumb, or the file itself. -
enterItem: Right or Enter on a folder keeps the crumbs up to the listed folder and adds the folder. -
previousPopup: Left goes to the folder above the listed one, skipping the file's crumb, which lists the same folder.
Closing resets trail to null, so the bar shows the file's path again.
Each open reads the folder with api.listDirectories, as the Files panel does, so ignored entries, folders-first order and the 5000 entry cap match. A request id drops late answers. The workspace crumb lists the folders with folderItems.
navRows filters with fuzzyMatch from the Command Palette: letters in order, best score first, ties in listing order, and highlight marks the matched letters. With no match, the list offers Search everywhere for "...", which closes the bar and calls fileSearch.open("files", query).
The list is the library's CrumbPopup, anchored to its crumb: it moves to <body> (the bar clips) and opens under the crumb, or above it near the bottom (crumbPlace).
edit.navigationBar is an Edit menu item with Cmd+Up on macOS and Alt+Home elsewhere, and a window command (WINDOW_COMMANDS), so it also works from the Files panel and the macOS terminal. Three details make it behave:
-
In the editor, CodeMirror binds Cmd+Up to "start of file" and handles it first.
IN_EDITORincommands/editorKeyPlan.tsputs the command's key (default or custom) in front of the editor keymap, unless an editor command was moved onto that key. -
In a text field,
textFieldKeepsinworkspaceShortcuts.tsleaves the key alone, so the commit message box keeps moving its caret. xterm's hidden text area does not count as a text field. -
While it is open,
shortcutsBlockedandoverlayOpenincludenavBarStore.isOpen, so other popups and window keys wait. The MCPclose_dialogtool knows it asnavigationBar.
| File | What it does |
|---|---|
src/lib/navBar/navBarModel.ts |
Crumbs, the trail rules, popup items and filtering |
src/lib/navBar/navBarStore.svelte.ts |
Which bar answers the jump, the floating bar, focus restore |
src/lib/navBar/NavigationBar.svelte, navBarView.ts, navListing.svelte.ts
|
The crumbs, the list, its keys and its loading |
src/lib/views/files/FileBar.svelte, FileView.svelte
|
Mounts the bar in the path bar, at the Top or under the code (Bottom), and claims it for the tab on screen |
src/lib/navBar/navTarget.svelte.ts |
What the floating bar points at |
src/lib/views/EmptyMain.svelte |
The bar on top or at the foot of the welcome screen, and its Navigation Bar button |
src/lib/stores/settingsData.ts, views/settings/AppearanceSettings.svelte
|
The fileToolbar setting and its Settings row |
src/lib/views/Workspace.svelte, workspaceLife.svelte.ts
|
The floating bar, and the text field check for the key |
ui/web/src/lib/components/CrumbPopup.svelte, logic/crumbs.ts
|
The list, placed next to its crumb |
src/lib/menu/menuSpec.ts, menuState.ts, menuActions.ts
|
Edit > Jump to Navigation Bar |
src/lib/views/workspaceShortcuts.ts, workspaceActions.ts
|
The window key, textFieldKeeps, the open guard |
src/lib/commands/editorKeyPlan.ts |
The key inside editors |
src/lib/help/shortcuts.ts |
The popup keys in the shortcuts window |
Lists open right away. Cmd+Up selects the last crumb and Down opens its list. Here the jump opens the file's folder at once, so typing a name works with one key less.
A file crumb lists its folder, with the file selected: a file has no contents of its own.
Three placements. Breadcrumbs can sit at the top, at the bottom, or hidden. Bottom moves the whole bar, so the file's tools stay next to its path. A hidden bar still answers the key, so the keyboard flow never depends on the layout.
Read on every open, no cache. A listing is one small backend call. Reading fresh means new files show up without watching, and nothing stays in memory after the bar closes.
Cmd+Up in the editor. Cmd+Up works in the editor too, and the user asked for the same feature. Cmd+Home still goes to the start of the file, and the key can be changed in Settings > Keyboard Shortcuts.
-
src/lib/navBar/navBarModel.test.ts: crumbs for one and several folders, nested repositories, paths outside the workspace, listed folders and selection, Left, entering items, workspace folders, filtering and highlights. -
src/lib/commands/editorKeyPlan.test.ts: the key in editors by default, with a custom key, removed, and when an editor command takes it. -
settingsData.test.ts: thefileToolbardefault and parsing. -
workspaceShortcuts.test.ts,registry.test.tsandmenuState.test.ts: Cmd+Up and Alt+Home,textFieldKeeps, the menu item. - The popup position, the floating bar and focus handling need a check in the real app.
- Changing the popup's keys: update
help/shortcuts.tsand the Navigation Bar page. - The path bar layout is described in How the path bar works.
- Retake
navigation-bar.png,navigation-bar-bottom.png,navigation-bar-hidden.png,empty-main.pngandsettings-appearance.png. See Docs and Screenshots.
These pages are generated from docs/wiki. To correct something, open a pull request against the source file; edits made here are overwritten.
Using Nibtree
- Getting Started
- Welcome Screen
- Workspaces
- Files Panel
- File Operations
- File Icons
- Rounded Panels
- Editor and Tabs
- Pin Reorder and Wrap Tabs
- Single Tab Title
- Split Editor
- New File and Unsaved Changes
- Unload Hidden Tabs
- Editing Code
- Code Appearance
- Markdown Editor
- Image and PDF Preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and Replace
- Changes and Commits
- Sign In Prompts
- Commit Box Layout
- Repository Actions
- Commit Options
- Ignoring Files
- Diffs
- Inline Diffs
- Staging View
- Revert a Change
- Resolving Conflicts
- Merge Tool
- Blame
- History and Log
- Merge Commits
- Branches and Tags
- Branches Popup
- Remotes
- Stashes
- Shelf
- Git Menu
- Git Dialogs
- Interactive Rebase
- Worktrees
- AI Agents
- AI Tasks
- AI Usage
- Keep Computer Awake
- Submodules
- Git LFS
- GitHub
- Git Console
- Terminal
- Terminal Features
- Scripts
- Navigation
- Menus
- Settings
- Settings Search
- Color Themes
- Settings Terminal and Automation
- Settings Files
- Updates
- Status Bar and Help
- Notifications
- Memory Use
- Clear Cache
- MCP and CLI
- Git Mergetool
- Keyboard Shortcuts
- Keyboard Shortcuts Editor
- Troubleshooting
- Troubleshooting Git
Developers
- Developer Guide
- Architecture
- Project Layout
- Backend
- How Folder Watching Works
- Folder Watching Bugs We Fixed
- How Workspace Files Work
- How the Preview Scheme Works
- Backend Services
- How Terminal Features Work
- Terminal Bugs We Fixed
- Frontend
- How the Rich Markdown Editor Works
- Rich Markdown Bugs We Fixed
- Git Menu Links
- Menu Keys and Routing
- Frontend Modules
- Blame Bugs We Fixed
- Project Color And Title Bar
- One Diff View
- Diff Bugs We Fixed
- Merge Tool Layouts
- Merge Tool Bugs We Fixed
- Color Theme Bugs We Fixed
- How the Connected Diff Works
- Rounded Panels Bugs We Fixed
- Update Bugs We Fixed
- Status Bar Bugs We Fixed
- MCP and CLI Bugs We Fixed
- Repository Actions Bugs We Fixed
- How the Changes Tab Works
- CodeMirror Patterns
- How the Cursor Works
- How Editor Features Work
- How the Path Bar Works
- Commands and Events
- Settings Reference
- Commands Workspace and Changes
- Commands Branches and Remotes
- Commands History and Extras
- Commands App and Tools
- Testing
- Test Suites
- Debugging
- Debugging with MCP
- Measuring Setting Memory
- How Terminal Memory Is Measured
- How Markdown Diagrams Work
- Releases and CI
- Publishing the Wiki
- Versioning and Changelog
- Browser Version Packages
- Browser Release Checks
- Docker Image
- Platforms and Signing
- Windows Support
- Windows Bugs We Fixed
- Windows MCP and CLI
- Docs and Screenshots
- UI Library
- UI Library MCP
- UI Library Bugs
- UI Library Migration
- Contributing
How features work
- Welcome screen
- Workspaces and folders
- Files panel
- File operations
- File icons
- Editor and tabs
- Pin, reorder and wrap tabs
- Single tab title
- Split editor
- New File and unsaved changes
- Unload hidden tabs
- Editing code
- Code appearance
- Markdown editor
- Image and PDF preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and replace
- Changes and commits
- Sign-in prompts
- Commit box layout
- Repository actions
- Commit options
- Ignoring files
- Diffs
- Inline diffs
- Staging view
- Revert a change
- Resolving conflicts
- Merge tool
- Blame
- History and log
- Merge commits
- Commit tabs
- Branches and tags
- Branches popup
- Remotes
- Stashes
- Shelf
- Git menu
- Git dialogs
- Interactive rebase
- Worktrees
- AI agents
- AI usage
- Keep computer awake
- AI tasks
- Submodules
- Git LFS
- GitHub account
- Git Console
- Back and Forward
- Integrated terminal
- Scripts tool window
- Menu bar
- Settings
- Search in Settings
- Color themes
- Rounded panels
- Updates and release channels
- Status bar and help links
- Notifications
- Memory readout and memory log
- Clear Cache
- MCP server and command line tool
- git mergetool mode