mirror of
https://github.com/litruv/Docs-Viewer.git
synced 2026-07-24 02:36:07 +10:00
Add loading state for links in file index and folder links
This commit is contained in:
@@ -224,11 +224,13 @@ export class DOMService {
|
|||||||
link.href = `?${doc.slug}`;
|
link.href = `?${doc.slug}`;
|
||||||
link.textContent = doc.title || doc.path.split('/').pop().replace('.md', '');
|
link.textContent = doc.title || doc.path.split('/').pop().replace('.md', '');
|
||||||
link.dataset.path = doc.path;
|
link.dataset.path = doc.path;
|
||||||
|
link.dataset.slug = doc.slug;
|
||||||
link.style.paddingLeft = `${(level * 0.6) + 0.8}rem`;
|
link.style.paddingLeft = `${(level * 0.6) + 0.8}rem`;
|
||||||
link.setAttribute('role', 'treeitem');
|
link.setAttribute('role', 'treeitem');
|
||||||
|
|
||||||
link.onclick = (e) => {
|
link.onclick = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
this.setLinkLoading(link);
|
||||||
this.eventBus.emit('navigation:requested', { slug: doc.slug });
|
this.eventBus.emit('navigation:requested', { slug: doc.slug });
|
||||||
history.pushState(null, '', link.href);
|
history.pushState(null, '', link.href);
|
||||||
if (window.innerWidth <= 1000) {
|
if (window.innerWidth <= 1000) {
|
||||||
@@ -239,11 +241,30 @@ export class DOMService {
|
|||||||
container.appendChild(link);
|
container.appendChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a link to loading state.
|
||||||
|
* @param {HTMLAnchorElement} link - The link element.
|
||||||
|
*/
|
||||||
|
setLinkLoading(link) {
|
||||||
|
this.clearAllLoading();
|
||||||
|
link.classList.add('loading');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears loading state from all links.
|
||||||
|
*/
|
||||||
|
clearAllLoading() {
|
||||||
|
this.elements.fileIndex.querySelectorAll('a.loading, .folder-link.loading').forEach(link => {
|
||||||
|
link.classList.remove('loading');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the active document highlight in the sidebar.
|
* Updates the active document highlight in the sidebar.
|
||||||
* @param {string} path - The path of the active document.
|
* @param {string} path - The path of the active document.
|
||||||
*/
|
*/
|
||||||
updateActiveDocument(path) {
|
updateActiveDocument(path) {
|
||||||
|
this.clearAllLoading();
|
||||||
this.elements.fileIndex.querySelectorAll('a').forEach(link => {
|
this.elements.fileIndex.querySelectorAll('a').forEach(link => {
|
||||||
const isActive = link.dataset.path === path;
|
const isActive = link.dataset.path === path;
|
||||||
link.classList.toggle('active', isActive);
|
link.classList.toggle('active', isActive);
|
||||||
@@ -326,6 +347,8 @@ export class DOMService {
|
|||||||
folderHeader.addEventListener('click', (e) => {
|
folderHeader.addEventListener('click', (e) => {
|
||||||
if (e.target.closest('.folder-link')) {
|
if (e.target.closest('.folder-link')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
const folderLink = e.target.closest('.folder-link');
|
||||||
|
this.setFolderLinkLoading(folderLink);
|
||||||
this.eventBus.emit('navigation:requested', { slug: doc.slug });
|
this.eventBus.emit('navigation:requested', { slug: doc.slug });
|
||||||
history.pushState(null, '', `?${doc.slug}`);
|
history.pushState(null, '', `?${doc.slug}`);
|
||||||
if (window.innerWidth <= 1000) {
|
if (window.innerWidth <= 1000) {
|
||||||
@@ -356,6 +379,15 @@ export class DOMService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a folder link to loading state.
|
||||||
|
* @param {HTMLAnchorElement} link - The folder link element.
|
||||||
|
*/
|
||||||
|
setFolderLinkLoading(link) {
|
||||||
|
this.clearAllLoading();
|
||||||
|
link.classList.add('loading');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scrolls smoothly to an element with header offset.
|
* Scrolls smoothly to an element with header offset.
|
||||||
* @param {HTMLElement} element - The element to scroll to.
|
* @param {HTMLElement} element - The element to scroll to.
|
||||||
|
|||||||
47
styles.css
47
styles.css
@@ -276,6 +276,38 @@ body {
|
|||||||
display: block;
|
display: block;
|
||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
|
position: relative;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#file-index a.loading {
|
||||||
|
pointer-events: none;
|
||||||
|
color: var(--ifm-color-content-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#file-index a.loading::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--ifm-color-primary);
|
||||||
|
animation: loading-progress 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading-progress {
|
||||||
|
0% {
|
||||||
|
width: 0%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
width: 70%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
width: 0%;
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#file-index a:hover {
|
#file-index a:hover {
|
||||||
@@ -334,6 +366,21 @@ body {
|
|||||||
right: 0;
|
right: 0;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-link.loading {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--ifm-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-link.loading i {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-header:hover .folder-link {
|
.folder-header:hover .folder-link {
|
||||||
|
|||||||
Reference in New Issue
Block a user