Skip to content

Commit e68608e

Browse files
committed
added horizontal progress scroll bar
1 parent 2c0ba39 commit e68608e

2 files changed

Lines changed: 87 additions & 51 deletions

File tree

css/main.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,20 @@ input:checked+.slider:before {
809809
/* Keep it aligned with the prose */
810810
}
811811

812+
/* ===== SCROLL PROGRESS BAR ===== */
813+
.scroll-progress-bar {
814+
position: fixed;
815+
top: 0;
816+
left: 0;
817+
height: 4px;
818+
width: 0%;
819+
background: var(--link-color);
820+
box-shadow: 0 0 8px var(--link-color);
821+
z-index: 9999;
822+
transition: width 0.05s linear;
823+
pointer-events: none;
824+
}
825+
812826
/* ===== SEARCH FEATURE ===== */
813827

814828
/* Floating Search Button (bottom-left) */

js/app.js

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
11
document.addEventListener('DOMContentLoaded', function () {
2+
3+
// ===== Scroll Progress Bar =====
4+
const progressBar = document.createElement('div');
5+
progressBar.className = 'scroll-progress-bar';
6+
document.body.appendChild(progressBar);
7+
8+
let ticking = false;
9+
window.addEventListener('scroll', function () {
10+
if (!ticking) {
11+
requestAnimationFrame(function () {
12+
const scrollTop = window.scrollY;
13+
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
14+
const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
15+
progressBar.style.width = progress + '%';
16+
ticking = false;
17+
});
18+
ticking = true;
19+
}
20+
});
21+
222
const themeToggle = document.getElementById('theme-toggle-icon');
323
const icon = themeToggle.querySelector('i');
424

@@ -27,59 +47,61 @@ document.addEventListener('DOMContentLoaded', function () {
2747
applyTheme(newTheme);
2848
});
2949

30-
// Custom Copy to Clipboard for Code Blocks
31-
const codeBlocks = document.querySelectorAll('pre');
32-
33-
// Create Toast Element for notification
34-
const toast = document.createElement('div');
35-
toast.className = 'toast-notification';
36-
toast.innerText = 'Copied to clipboard';
37-
document.body.appendChild(toast);
38-
39-
codeBlocks.forEach(block => {
40-
// Create the copy button using an icon
41-
const copyButton = document.createElement('button');
42-
copyButton.className = 'copy-code-btn';
43-
copyButton.innerHTML = '<i class="far fa-copy"></i>';
44-
copyButton.setAttribute('aria-label', 'Copy code to clipboard');
45-
46-
// Add the button to the pre block
47-
block.appendChild(copyButton);
48-
49-
// Add the click event listener
50-
copyButton.addEventListener('click', () => {
51-
const code = block.querySelector('code');
52-
let textToCopy = '';
53-
54-
if (code) {
55-
textToCopy = code.innerText;
56-
} else {
57-
// Remove the button from the copied text if no inner code tag is found
58-
const clone = block.cloneNode(true);
59-
const btn = clone.querySelector('.copy-code-btn');
60-
if (btn) clone.removeChild(btn);
61-
textToCopy = clone.innerText;
62-
}
63-
64-
navigator.clipboard.writeText(textToCopy).then(() => {
65-
// Show toast notification
66-
toast.classList.add('show');
67-
68-
// Change icon to a checkmark
69-
copyButton.innerHTML = '<i class="fas fa-check"></i>';
70-
copyButton.classList.add('copied');
71-
72-
setTimeout(() => {
73-
// Hide toast and revert icon
74-
toast.classList.remove('show');
75-
copyButton.innerHTML = '<i class="far fa-copy"></i>';
76-
copyButton.classList.remove('copied');
77-
}, 2500);
78-
}).catch(err => {
79-
console.error('Failed to copy text: ', err);
50+
// Custom Copy to Clipboard for Code Blocks (blog posts only)
51+
const codeBlocks = document.querySelectorAll('.post-content-main pre');
52+
53+
// Only create the toast if there are code blocks on this page
54+
if (codeBlocks.length > 0) {
55+
const toast = document.createElement('div');
56+
toast.className = 'toast-notification';
57+
toast.innerText = 'Copied to clipboard';
58+
document.body.appendChild(toast);
59+
60+
codeBlocks.forEach(block => {
61+
// Create the copy button using an icon
62+
const copyButton = document.createElement('button');
63+
copyButton.className = 'copy-code-btn';
64+
copyButton.innerHTML = '<i class="far fa-copy"></i>';
65+
copyButton.setAttribute('aria-label', 'Copy code to clipboard');
66+
67+
// Add the button to the pre block
68+
block.appendChild(copyButton);
69+
70+
// Add the click event listener
71+
copyButton.addEventListener('click', () => {
72+
const code = block.querySelector('code');
73+
let textToCopy = '';
74+
75+
if (code) {
76+
textToCopy = code.innerText;
77+
} else {
78+
// Remove the button from the copied text if no inner code tag is found
79+
const clone = block.cloneNode(true);
80+
const btn = clone.querySelector('.copy-code-btn');
81+
if (btn) clone.removeChild(btn);
82+
textToCopy = clone.innerText;
83+
}
84+
85+
navigator.clipboard.writeText(textToCopy).then(() => {
86+
// Show toast notification
87+
toast.classList.add('show');
88+
89+
// Change icon to a checkmark
90+
copyButton.innerHTML = '<i class="fas fa-check"></i>';
91+
copyButton.classList.add('copied');
92+
93+
setTimeout(() => {
94+
// Hide toast and revert icon
95+
toast.classList.remove('show');
96+
copyButton.innerHTML = '<i class="far fa-copy"></i>';
97+
copyButton.classList.remove('copied');
98+
}, 2500);
99+
}).catch(err => {
100+
console.error('Failed to copy text: ', err);
101+
});
80102
});
81103
});
82-
});
104+
}
83105
});
84106

85107

0 commit comments

Comments
 (0)