new navbar component - #725
Conversation
…@3.1.3-13 pane-registry@3.1.2-2 activitystreams-pane@1.0.3-4 chat-pane@3.0.4-3 contacts-pane@3.2.1-5 folder-pane@3.1.1-2 issue-pane@3.0.3-1 meeting-pane@3.0.3-1 profile-pane@3.2.3-4 source-pane@3.1.1-5) (latest: rdflib@2.4.0)
There was a problem hiding this comment.
Pull request overview
This PR introduces a new solid-panes-navbar web component and wires it into the main page flow, while also refactoring some outline/pod-storage logic and adjusting build/watch behavior in Vite.
Changes:
- Add a new Navbar web component (
solid-panes-navbar) plus main-page creation/insert logic. - Refactor pod storage discovery and folder-pane item creation into new outline utilities, and update outline manager behavior/UI.
- Update Vite config to speed up
vite build --watchand ensure async/nested plugins (incl. babel) are preserved; bump package version and update lockfile.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.mts | Adds watch-mode optimizations and async plugin flattening for reliable builds. |
| src/social/socialPane.css | Tweaks spacing and removes redundant .social-pane block. |
| src/registerPanes.js | Changes pane registration (notably default/internal panes). |
| src/outline/podUtils.ts | New helper for discovering pod storage containers + loading container turtle. |
| src/outline/folderPaneUtils.ts | New helper for producing folder-pane menu items for pod storages. |
| src/outline/manager.js | Integrates new pod/folder helpers; adjusts navbar visibility; removes parts of icon-tray logic. |
| src/outline/manager.css | Updates .tdFlex styling used by outline header row. |
| src/mainPage/navbar.ts | Creates and inserts the new navbar component; builds menu items. |
| src/mainPage/index.ts | Initializes navbar alongside the existing header. |
| src/components/navbar/Navbar.ts | Implements the solid-panes-navbar component. |
| src/components/navbar/Navbar.styles.css | Adds navbar/button styles (nested under :host). |
| src/components/navbar/index.ts | Exports the Navbar component module. |
| package.json | Version bump and removal of dependency overrides. |
| package-lock.json | Lockfile updates including nested dependency installs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| register(tableViewPane) | ||
|
|
||
| // Fallback totally generic: | ||
| register(defaultPane) | ||
| // register(defaultPane) | ||
|
|
| register(sharingPane) | ||
|
|
||
| // The internals pane is always (almost?) the last as it is the least user-friendly | ||
| register(internalPane) | ||
| // register(internalPane) // under the hood has been removed with new design | ||
|
|
| "pane-registry": "3.1.2-2", | ||
| "profile-pane": "3.2.3-3", | ||
| "rdflib": "2.4.0", | ||
| "solid-logic": "4.0.8-1", | ||
| "solid-namespace": "^0.5.4", | ||
| "solid-ui": "3.1.3-13", | ||
| "source-pane": "3.1.1-4" | ||
| }, | ||
| "overrides": { | ||
| "rdflib": "$rdflib", | ||
| "solid-logic": "$solid-logic", | ||
| "solid-ui": "$solid-ui", | ||
| "pane-registry": "$pane-registry" | ||
| }, | ||
| "devDependencies": { |
| createNavItem('Storage', () => { | ||
| const folderPanes = podStorages.map((pod, index) => createFolderPaneItem(outliner?.context?.session?.paneRegistry?.byName('folder'), pod, index)) | ||
| if (folderPanes.length === 0) { | ||
| console.warn('Folder pane is not registered') |
There was a problem hiding this comment.
maybe you should also add this message for profile and social.
| const relevantPanes = panes.list.filter( | ||
| pane => pane.label(subject, context) && !pane.global | ||
| ) | ||
| if (relevantPanes.length === 0) { |
There was a problem hiding this comment.
if there are no relevant panes now what will get shown instead? The folder-pane may need this, I can't be sure yet though just a note to check.
There was a problem hiding this comment.
relevant panes exists but is not in use in the menus anymore. the menus are fixed.
The relevant panes comes into play in the 3 dot menu
| } | ||
|
|
||
| async function expandedHeaderTR (subject, requiredPane, options) { | ||
| async function determineFirstPane (options = {}) { |
There was a problem hiding this comment.
I see perhaps it's here, why we don't need the relevant pane ... return 'internal'?
There was a problem hiding this comment.
The menu items are not fixed.
| } | ||
|
|
||
| async function renderPaneIconTray (td, options = {}) { | ||
| // Icon tray removed: this UI is no longer needed. |
There was a problem hiding this comment.
I'm thinking that this will basically be in that 3 dots menu (at least source pane, maybe others). so anything that was shown here can be accessed still.
| }) | ||
| ) | ||
| // Pane icon tray removed: preserve first-pane selection without rendering the tray. | ||
| await determineFirstPane({ hideList: showHeader }) |
There was a problem hiding this comment.
I'm just making a note here, because I need to recheck this.
I want to check is this only the tray... because I believe the header also has the file name for instance and I'm going to need to move the tray, so we should technically still have the header but instead of the icon tray they will just be menu items in the 3 dots.
Basically I think it should still be shown, definitely for a pod "owner" (logged in, looking at your own profile). I'm not sure about the other 2 viewerModes I need to recheck the design.
i'm kind of thinking that we need the viewerMode that is in profile-pane to be at a higher level here in solid-panes.
There was a problem hiding this comment.
I brought down your code and see that the file name is still there and a few icons like the pane it is, source, and sharing. this is good. so I can just move them to the 3 dots in a different PR that should work, the header is still there. Interestingly, and I haven't gone through the manager code yet in detail but this change you made did not effect the containers.
Also, (I am just making notes for consideration). In the new design the containers are instead shown in a square div with the 3 dots at the corner.
There was a problem hiding this comment.
Yes yes.
Manager created the header and icon tray for each resource you open.
It does this here. I moved the render of the iconTray only when the header exists so that we can still edit files. This is the code you will need to refactor and use in your menu items later.
| showSolidPanesNavbar() | ||
| } | ||
|
|
||
| table = table || outlineContainer // if does not exist create a compatible host in the current shell |
There was a problem hiding this comment.
you probably had to do it for some reason, but funny to move this below the check. Seems like it shoudl stay above it.
|
|
||
| // Fallback totally generic: | ||
| register(defaultPane) | ||
| // register(defaultPane) |
There was a problem hiding this comment.
this is really interesting. it's actually a Developer only pane, it's the one that says "about".
why would it say for instance fallback totally generic when it could only be shown for someone who has Developer as their user preference.
I think we should discuss what it does today and if we still want it for people who have Developer selected.

There was a problem hiding this comment.
Yes, my thoughts too. This is a pane we should theoretically get rid of I believe.
|
|
||
| // The internals pane is always (almost?) the last as it is the least user-friendly | ||
| register(internalPane) | ||
| // register(internalPane) // under the hood has been removed with new design |
There was a problem hiding this comment.
| "source-pane": "3.1.1-4" | ||
| }, | ||
| "overrides": { | ||
| "rdflib": "$rdflib", |
There was a problem hiding this comment.
Because rdflib is not in my solidos setup I didn't have to remove this one. Thought I'd just mention.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…@3.1.3-13 pane-registry@3.1.2-2 activitystreams-pane@1.0.3-4 chat-pane@3.0.4-3 contacts-pane@3.2.1-5 folder-pane@3.1.1-2 issue-pane@3.0.3-1 meeting-pane@3.0.3-1 profile-pane@3.2.3-4 source-pane@3.1.1-5) (latest: rdflib@2.4.0)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Prompot: When I use the header buttons and sleect something I want to hide the navbar. When I refresh the page I want the navbar to show also when I use any item form the navbar. Co-authored-by: GitHub Copilot (claude-sonnet-4.6) <copilot@github.com>
…@3.1.3-13 pane-registry@3.1.2-2 activitystreams-pane@1.0.3-4 chat-pane@3.0.4-3 contacts-pane@3.2.1-5 folder-pane@3.1.1-2 issue-pane@3.0.3-1 meeting-pane@3.0.3-1 profile-pane@3.2.3-4 source-pane@3.1.1-5) (latest: rdflib@2.4.0)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 18 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (7)
src/mainPage/header.ts:54
- Profile selection uses GotoSubject() with the current URL as the subject, so OutlineManager won’t push a history entry and paneName won’t update. That can cause refreshUI to re-render a different pane than the one the user last selected.
if (me) {
const profilePane = await getProfilePaneFromURI(me)
outliner.GotoSubject(sym(window.location.href), true, profilePane, true, undefined, outlineView, false)
}
}
src/mainPage/header.ts:64
- Friends selection doesn’t update window.history.state.paneName, so refreshUI may not preserve the selected pane across environment-driven refreshes.
if (me) {
const socialPane = await getSocialPaneFromURI(me)
outliner.GotoSubject(sym(window.location.href), true, socialPane, true, undefined, outlineView, false)
}
}
src/mainPage/header.ts:43
- Storage menu selections don’t update window.history.state.paneName, so refreshUI (and any UI relying on history.state) can revert to an old pane after an environment refresh. Consider updating the history state when the user selects a pane.
This issue also appears in the following locations of the same file:
- line 50
- line 60
hideNavbar()
if (me) {
outliner.GotoSubject(sym(window.location.href), true, pane, true, undefined, outlineView, false)
}
}
src/mainPage/navbar.ts:72
- Navbar pane selection always calls GotoSubject() with the current page URL as the subject, so OutlineManager never updates window.history.state.paneName when switching panes (no URL change). That leaves selectedPaneName stale and breaks refreshUI’s ability to re-render the currently selected pane, and it can also mark multiple storage items selected at once.
if (webId) {
menuItems.push(
createNavItem('Profile', async () => {
const profilePane = await getProfilePaneFromURI(webId)
outliner.GotoSubject(subject, true, profilePane, true, undefined, outlineView)
src/mainPage/index.ts:51
- initMainPage reads window.history.state?.paneName but never uses it to restore the previously selected pane. As a result, reloading the page (or arriving via history navigation) won’t reopen the last pane even though refreshUI later depends on history.state.paneName.
const historyPane = window.history.state?.paneName
const initialPane = !historyPane && isWebIdUri(subject)
? await getProfilePaneFromURI(subject)
: undefined
src/components/navbar/Navbar.ts:33
- NavbarMenuItem.onSelected is commonly provided as an async function (e.g. mainPage/navbar.ts). The component currently calls it without handling the returned Promise, which can lead to unhandled promise rejections and hard-to-debug errors if a pane load fails.
private selectItem (item: NavbarMenuItem) {
this.navbarItems = this.navbarItems.map(menuItem => ({
...menuItem,
selected: menuItem === item
}))
src/utils/paneUtils.ts:95
- The exported helper name
getFolderPaneforStoragehas a typo/inconsistent casing (“Panefor”). Since this is a new API surface, it’s a good time to rename it before it becomes part of the public contract.
export async function getFolderPaneforStorage (podUrl: NamedNode, label?: string): Promise<PaneItem | null> {


This creates a new Navbar web component.
I removed the top icon tray nav but kept it for the resources in the file explorer for now.