-
-
Notifications
You must be signed in to change notification settings - Fork 500
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor sidebar persistence logic for better slow device performance (…
…#2242) Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com>
- Loading branch information
Showing
6 changed files
with
98 additions
and
37 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@astrojs/starlight": patch | ||
--- | ||
|
||
Refactors the logic for persisting and restoring sidebar state across navigations for better performance on slow or busy devices |
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
--- | ||
/* | ||
This component is designed to wrap the tree of `<SidebarSublist>` components in the sidebar. | ||
It does the following: | ||
- Wraps the tree in an `<sl-sidebar-state-persist>` custom element | ||
- Before the tree renders, adds an inline script which loads state and defines | ||
the behaviour for the `<sl-sidebar-restore>` custom element. | ||
- After the tree renders, adds an inline script which restores the sidebar scroll state. | ||
Notes: | ||
- On smaller viewports, restoring state is skipped as the sidebar is collapsed inside a menu. | ||
- The state is parsed from session storage and restored. | ||
- This is a progressive enhancement, so any errors are swallowed silently. | ||
*/ | ||
import type { Props } from '../props'; | ||
import { getSidebarHash } from '../utils/navigation'; | ||
const hash = getSidebarHash(Astro.props.sidebar); | ||
declare global { | ||
interface Window { | ||
/** Restored scroll position. Briefly stored on the `window` global to pass between inline scripts. */ | ||
_starlightScrollRestore?: number; | ||
} | ||
} | ||
--- | ||
|
||
<sl-sidebar-state-persist data-hash={hash}> | ||
<script is:inline> | ||
(() => { | ||
try { | ||
if (!matchMedia('(min-width: 50em)').matches) return; | ||
/** @type {HTMLElement | null} */ | ||
const target = document.querySelector('sl-sidebar-state-persist'); | ||
const state = JSON.parse(sessionStorage.getItem('sl-sidebar-state') || '0'); | ||
if (!target || !state || target.dataset.hash !== state.hash) return; | ||
window._starlightScrollRestore = state.scroll; | ||
customElements.define( | ||
'sl-sidebar-restore', | ||
class SidebarRestore extends HTMLElement { | ||
connectedCallback() { | ||
try { | ||
const idx = parseInt(this.dataset.index || ''); | ||
const details = this.closest('details'); | ||
if (details && typeof state.open[idx] === 'boolean') details.open = state.open[idx]; | ||
} catch {} | ||
} | ||
} | ||
); | ||
} catch {} | ||
})(); | ||
</script> | ||
|
||
<slot /> | ||
|
||
<script is:inline> | ||
(() => { | ||
const scroller = document.getElementById('starlight__sidebar'); | ||
if (!window._starlightScrollRestore || !scroller) return; | ||
scroller.scrollTop = window._starlightScrollRestore; | ||
delete window._starlightScrollRestore; | ||
})(); | ||
</script> | ||
</sl-sidebar-state-persist> | ||
|
||
<style> | ||
sl-sidebar-state-persist { | ||
display: contents; | ||
} | ||
</style> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
/** Unique symbol for storing a running index in `locals`. */ | ||
const currentGroupIndexSymbol = Symbol.for('starlight-sidebar-group-index'); | ||
const locals = Astro.locals as Record<typeof currentGroupIndexSymbol, number>; | ||
/** The current sidebar group’s index retrieved from `locals` if set, starting at `0`. */ | ||
const index = locals[currentGroupIndexSymbol] || 0; | ||
// Increment the index for the next instance. | ||
locals[currentGroupIndexSymbol] = index + 1; | ||
--- | ||
|
||
<sl-sidebar-restore data-index={index}></sl-sidebar-restore> |
This file contains 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