All checks were successful
Build and Deploy Hugo Site / build-and-deploy (push) Successful in 9s
118 lines
3.6 KiB
JavaScript
118 lines
3.6 KiB
JavaScript
console.log('This site was generated by Hugo.');
|
|
|
|
// Theme toggle functionality
|
|
(function() {
|
|
const STORAGE_KEY = 'theme-preference';
|
|
|
|
const getColorPreference = () => {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (stored) {
|
|
return stored;
|
|
}
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
};
|
|
|
|
const setPreference = (theme) => {
|
|
localStorage.setItem(STORAGE_KEY, theme);
|
|
reflectPreference(theme);
|
|
};
|
|
|
|
const reflectPreference = (theme) => {
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
const button = document.querySelector('#theme-toggle');
|
|
if (button) {
|
|
button.setAttribute('aria-label', theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme');
|
|
button.textContent = theme === 'dark' ? '☀️' : '🌙';
|
|
}
|
|
};
|
|
|
|
// Set initial theme
|
|
const theme = getColorPreference();
|
|
reflectPreference(theme);
|
|
|
|
// Set up toggle button when DOM is ready
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
const button = document.querySelector('#theme-toggle');
|
|
if (button) {
|
|
button.addEventListener('click', () => {
|
|
const currentTheme = document.documentElement.getAttribute('data-theme');
|
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
setPreference(newTheme);
|
|
});
|
|
}
|
|
});
|
|
|
|
// Listen for system theme changes
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ({ matches: isDark }) => {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (!stored) {
|
|
setPreference(isDark ? 'dark' : 'light');
|
|
}
|
|
});
|
|
})();
|
|
|
|
// Typing animation for subtitle with mistakes
|
|
(function() {
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
const subtitleElement = document.querySelector('.site-header .subtitle');
|
|
if (!subtitleElement) return;
|
|
|
|
const fullText = subtitleElement.textContent;
|
|
subtitleElement.textContent = '';
|
|
|
|
// Define the typing sequence with mistakes happening naturally
|
|
const sequence = [
|
|
{ action: 'type', text: "echo 'Coding, family, life'; // by Chris Sm" },
|
|
{ action: 'type', text: 't' },
|
|
{ action: 'type', text: 'i' },
|
|
{ action: 'type', text: 'h' },
|
|
{ action: 'pause', duration: 400 },
|
|
{ action: 'backspace', count: 3 },
|
|
{ action: 'pause', duration: 200 },
|
|
{ action: 'type', text: 'ith' }
|
|
];
|
|
|
|
let currentText = '';
|
|
let sequenceIndex = 0;
|
|
let charIndex = 0;
|
|
|
|
function executeSequence() {
|
|
if (sequenceIndex >= sequence.length) {
|
|
return;
|
|
}
|
|
|
|
const step = sequence[sequenceIndex];
|
|
|
|
if (step.action === 'type') {
|
|
if (charIndex < step.text.length) {
|
|
currentText += step.text[charIndex];
|
|
subtitleElement.textContent = currentText;
|
|
charIndex++;
|
|
setTimeout(executeSequence, 80 + Math.random() * 40);
|
|
} else {
|
|
charIndex = 0;
|
|
sequenceIndex++;
|
|
setTimeout(executeSequence, 100);
|
|
}
|
|
} else if (step.action === 'backspace') {
|
|
if (charIndex < step.count) {
|
|
currentText = currentText.slice(0, -1);
|
|
subtitleElement.textContent = currentText;
|
|
charIndex++;
|
|
setTimeout(executeSequence, 60);
|
|
} else {
|
|
charIndex = 0;
|
|
sequenceIndex++;
|
|
setTimeout(executeSequence, 100);
|
|
}
|
|
} else if (step.action === 'pause') {
|
|
sequenceIndex++;
|
|
setTimeout(executeSequence, step.duration);
|
|
}
|
|
}
|
|
|
|
// Start typing after a short delay
|
|
setTimeout(executeSequence, 500);
|
|
});
|
|
})();
|