Last updated: First published:
Updating the Sidebar
The story to be told about the sidebar is a bit convoluted.
Visit the corresponding section in the overview to see where we are in the big picture of The Bag’s Starlight support.
The Bag’s view transition support keeps the app frame of the Starlight site unchanged and only swaps the main-frame inside it on transitions. While you could use the sidebar for navigation this way, it would look a bit odd if the current page marker wouldn’t change. So we need some script to update the current page marker in the sidebar ourselves. And that’s it.
At least that’s what I thought.
What it Could have Been
And that would have been a a nice exercise:
- Remove the
aria-current="page"
attribute where ever it exists ine.newDocument
. This is the marker we would update. - Also in
e.newDocument
, find the sidebar entry that links toe.to.href
. Add thearia-current="page"
to that element. Done. Run all that directly after the loader has fetched the new DOM.
Splash! Sidebar Changes on Navigation
To be honest, I did the exercise above for v1.7.0 of The Bag and thought it was good as it was. But then I learned it wasn’t↗.
I had another dependency on Starlight’s page structure that I wasn’t aware of before: If you use the splash
template, the sidebar is not created at all.
You may have notice that the Jotter is linked from The Bag’s homepage. It doesn’t use a splash screen as entry. But almost all others Starlight sites do.
Starting with a splash screen creates an app frame without a sidebar. If you jump to a page with a doc
template, we keep this app frame and never show a sidebar (until we force the browser to do a full page load). Equally irritating, if you navigate from a doc
page to a splash
page, we retain the app frame, which bravely continues to display the sidebar on the splash screen.
So this is the point at which the first assumption proved to be wrong.
Swapping the Sidebar
We can’t just add data-vtbot-replace
to the sidebar and trust the <ReplacementSwap/>
component to do it right. It would work to throw away the sidebar when navigating to a splash page, but it might not add a missing sidebar. But the special handling we need for the sidebar is very similar to what ReplacementSwap
does internally.
Revealed: This now reveals what is behind Line 20 of the StarlightConnector.
- If we do have a sidebar, but the new page shouldn’t, we drop it.
- If we don’t have a sidebar but the new page should have one, we add it.
- If both pages have a sidebar, we copy the new content to the current sidebar.
Note that we try to avoid copying the sidebar itself to keep the current scroll position for longer sidebars.
If a Starlight site decides to render page-specific content in the sidebar, that would also work quite well.
And the Current Page Marker?
That does not need special attention any more. The aria-current="page"
is automatically updated when copying the sidebar content. This would even work if the collapse
The Twist in the Tale
When I showed this to @Chris, the mastermind behind Starlight, he mentioned that people would like it if the sidebar remembered the state of the collapsed categories during navigation.
Like the scroll position, this information is a inherent part of the state of the sidebar. If you don’t change it during navigation, it should still be the same on the next page.
I was a little confused.
- I hadn’t actively thought about this kind of state before.
- I had the desired behavior in my first version where i didn’t handle the sidebar specifically, but just updated the highlighting of the current page. This feature went completely unnoticed by me.
- I just ruined it by overriding this valuable information about the categories by replacing the sidebar content.
I’ve been thinking about this: people who want the status of categories saved are much more common than authors who want to change the sidebar content. I could just delete the last 6 lines of updateSidebar() and be done.
On the other hand: Starlight will provide a built-in solution to maintain the state of the sidebar during navigation, regardless of view transitions. For this to work, the current version of updateSidebar()
could be much more robust, but who knows. And then there would be the use case of authors changing the sidebar content depending on the current page …
If you don’t know what to do, make it someone else’s problem. I add a switch that defaults to the “only update the current page marker” version and in this case, skips replacing existing sidebar content in updateSidebar()
. Authors can set it to what fits best for their site.
Luckily, I still had that code I sketched at the beginning of this page.
Revealed: This listing reveals what’s behind Line 14 of the StarlightConnector.
It now again runs by default. You can switch it off in favor of the “replace existing sidebar content on navigation” semantics. Maybe this might be necessary when Starlight comes with its own sidebar state handling. Here is how:
And the Mobile Menu Button?
Revealed: How do we close the mobile menu on navigation? This reveals what is hidden behind Line 15 of the StarlightConnector.
It just presses the escape key if it detects that the mobile menu is open.