Sliding indicator on OnThisPage

pull/8288/head
Puru Vijay 4 years ago
parent f65e2600ce
commit 71826ae8a8

@ -24,10 +24,12 @@
let positions = []; let positions = [];
/** @type {HTMLElement} */ /** @type {HTMLElement} */
let containerEl; let container_el;
let show_contents = false; let show_contents = false;
let glider_index = 0;
onMount(async () => { onMount(async () => {
await document.fonts.ready; await document.fonts.ready;
@ -86,12 +88,14 @@
); );
} }
$: glider_index = details.sections.findIndex(({ slug }) => hash.replace('#', '') === slug);
afterUpdate(() => { afterUpdate(() => {
// bit of a hack — prevent sidebar scrolling if // bit of a hack — prevent sidebar scrolling if
// TOC is open on mobile, or scroll came from within sidebar // TOC is open on mobile, or scroll came from within sidebar
if (show_contents && window.innerWidth < 832) return; if (show_contents && window.innerWidth < 832) return;
const active = containerEl.querySelector('.active'); const active = container_el.querySelector('.active');
if (active) { if (active) {
const { top, bottom } = active.getBoundingClientRect(); const { top, bottom } = active.getBoundingClientRect();
@ -100,13 +104,13 @@
const max = window.innerHeight - 200; const max = window.innerHeight - 200;
if (top > max) { if (top > max) {
containerEl.scrollBy({ container_el.scrollBy({
top: top - max, top: top - max,
left: 0, left: 0,
behavior: 'smooth', behavior: 'smooth',
}); });
} else if (bottom < min) { } else if (bottom < min) {
containerEl.scrollBy({ container_el.scrollBy({
top: bottom - min, top: bottom - min,
left: 0, left: 0,
behavior: 'smooth', behavior: 'smooth',
@ -118,7 +122,7 @@
<svelte:window on:scroll={highlight} on:resize={update} on:hashchange={() => select($page.url)} /> <svelte:window on:scroll={highlight} on:resize={update} on:hashchange={() => select($page.url)} />
<aside class="on-this-page" bind:this={containerEl}> <aside class="on-this-page" bind:this={container_el}>
<h2>On this page</h2> <h2>On this page</h2>
<nav> <nav>
<ul> <ul>
@ -126,6 +130,7 @@
{#each details.sections as { title, slug }} {#each details.sections as { title, slug }}
<li><a href={`#${slug}`} class:active={`#${slug}` === hash}>{title}</a></li> <li><a href={`#${slug}`} class:active={`#${slug}` === hash}>{title}</a></li>
{/each} {/each}
<div class="glider" style:transform="translateY({(glider_index + 1) * 100}%)" />
</ul> </ul>
</nav> </nav>
</aside> </aside>
@ -153,6 +158,7 @@
} }
ul { ul {
position: relative;
list-style: none; list-style: none;
} }
@ -161,7 +167,9 @@
padding: 0.3rem 0.5rem; padding: 0.3rem 0.5rem;
color: var(--sk-text-3); color: var(--sk-text-3);
font-size: 1.6rem; font-size: 1.6rem;
border-left: 2px solid transparent; white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
a:hover { a:hover {
@ -169,8 +177,16 @@
background: var(--sk-back-3); background: var(--sk-back-3);
} }
a.active { .glider {
position: absolute;
top: 0;
left: 0;
z-index: -1;
width: 100%;
height: 30px;
background: var(--sk-back-3); background: var(--sk-back-3);
border-left: 2px solid transparent;
border-left-color: var(--sk-theme-1); border-left-color: var(--sk-theme-1);
transition: transform 0.15s ease-out;
} }
</style> </style>

Loading…
Cancel
Save