Move docs to /docs for GitHub Pages
GitHub Pages is configured to serve from /docs in main branch. Moved documentation site from plugins/compounding-engineering/docs/ to repository root /docs folder. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
225
docs/js/main.js
Normal file
225
docs/js/main.js
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* Compounding Engineering Documentation
|
||||
* Main JavaScript functionality
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initMobileNav();
|
||||
initSmoothScroll();
|
||||
initCopyCode();
|
||||
initThemeToggle();
|
||||
});
|
||||
|
||||
/**
|
||||
* Mobile Navigation Toggle
|
||||
*/
|
||||
function initMobileNav() {
|
||||
const mobileToggle = document.querySelector('[data-mobile-toggle]');
|
||||
const navigation = document.querySelector('[data-navigation]');
|
||||
|
||||
if (!mobileToggle || !navigation) return;
|
||||
|
||||
mobileToggle.addEventListener('click', () => {
|
||||
navigation.classList.toggle('open');
|
||||
mobileToggle.classList.toggle('active');
|
||||
|
||||
// Update aria-expanded
|
||||
const isOpen = navigation.classList.contains('open');
|
||||
mobileToggle.setAttribute('aria-expanded', isOpen);
|
||||
});
|
||||
|
||||
// Close menu when clicking outside
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!mobileToggle.contains(event.target) && !navigation.contains(event.target)) {
|
||||
navigation.classList.remove('open');
|
||||
mobileToggle.classList.remove('active');
|
||||
mobileToggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
// Close menu when clicking a nav link
|
||||
navigation.querySelectorAll('.nav-link').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
navigation.classList.remove('open');
|
||||
mobileToggle.classList.remove('active');
|
||||
mobileToggle.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Smooth Scroll for Anchor Links
|
||||
*/
|
||||
function initSmoothScroll() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function(e) {
|
||||
const targetId = this.getAttribute('href');
|
||||
if (targetId === '#') return;
|
||||
|
||||
const targetElement = document.querySelector(targetId);
|
||||
if (!targetElement) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const navHeight = document.querySelector('.nav-container')?.offsetHeight || 0;
|
||||
const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - navHeight - 24;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
// Update URL without jumping
|
||||
history.pushState(null, null, targetId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Code Functionality
|
||||
*/
|
||||
function initCopyCode() {
|
||||
document.querySelectorAll('.card-code-block').forEach(block => {
|
||||
// Create copy button
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'copy-btn';
|
||||
copyBtn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
||||
copyBtn.setAttribute('aria-label', 'Copy code');
|
||||
copyBtn.setAttribute('title', 'Copy to clipboard');
|
||||
|
||||
// Style the button
|
||||
copyBtn.style.cssText = `
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
padding: 6px 10px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
color: #94a3b8;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
// Make parent relative for positioning
|
||||
block.style.position = 'relative';
|
||||
block.appendChild(copyBtn);
|
||||
|
||||
// Show/hide on hover
|
||||
block.addEventListener('mouseenter', () => {
|
||||
copyBtn.style.opacity = '1';
|
||||
});
|
||||
|
||||
block.addEventListener('mouseleave', () => {
|
||||
copyBtn.style.opacity = '0';
|
||||
});
|
||||
|
||||
// Copy functionality
|
||||
copyBtn.addEventListener('click', async () => {
|
||||
const code = block.querySelector('code');
|
||||
if (!code) return;
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(code.textContent);
|
||||
copyBtn.innerHTML = '<i class="fa-solid fa-check"></i>';
|
||||
copyBtn.style.color = '#34d399';
|
||||
|
||||
setTimeout(() => {
|
||||
copyBtn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
||||
copyBtn.style.color = '#94a3b8';
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err);
|
||||
copyBtn.innerHTML = '<i class="fa-solid fa-xmark"></i>';
|
||||
copyBtn.style.color = '#f87171';
|
||||
|
||||
setTimeout(() => {
|
||||
copyBtn.innerHTML = '<i class="fa-regular fa-copy"></i>';
|
||||
copyBtn.style.color = '#94a3b8';
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme Toggle (Light/Dark)
|
||||
*/
|
||||
function initThemeToggle() {
|
||||
// Check for saved theme preference or default to dark
|
||||
const savedTheme = localStorage.getItem('theme') || 'dark';
|
||||
document.documentElement.className = `theme-${savedTheme}`;
|
||||
|
||||
// Create theme toggle button if it doesn't exist
|
||||
const existingToggle = document.querySelector('[data-theme-toggle]');
|
||||
if (existingToggle) {
|
||||
existingToggle.addEventListener('click', toggleTheme);
|
||||
updateThemeToggleIcon(existingToggle, savedTheme);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
const html = document.documentElement;
|
||||
const currentTheme = html.classList.contains('theme-dark') ? 'dark' : 'light';
|
||||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
|
||||
html.className = `theme-${newTheme}`;
|
||||
localStorage.setItem('theme', newTheme);
|
||||
|
||||
const toggle = document.querySelector('[data-theme-toggle]');
|
||||
if (toggle) {
|
||||
updateThemeToggleIcon(toggle, newTheme);
|
||||
}
|
||||
}
|
||||
|
||||
function updateThemeToggleIcon(toggle, theme) {
|
||||
const icon = toggle.querySelector('i');
|
||||
if (icon) {
|
||||
icon.className = theme === 'dark' ? 'fa-solid fa-sun' : 'fa-solid fa-moon';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection Observer for Animation on Scroll
|
||||
*/
|
||||
function initScrollAnimations() {
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
document.querySelectorAll('.agent-card, .command-card, .skill-card, .mcp-card, .stat-card').forEach(card => {
|
||||
card.style.opacity = '0';
|
||||
card.style.transform = 'translateY(20px)';
|
||||
card.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
|
||||
observer.observe(card);
|
||||
});
|
||||
}
|
||||
|
||||
// Add visible class styles
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.agent-card.visible,
|
||||
.command-card.visible,
|
||||
.skill-card.visible,
|
||||
.mcp-card.visible,
|
||||
.stat-card.visible {
|
||||
opacity: 1 !important;
|
||||
transform: translateY(0) !important;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Initialize scroll animations after a short delay
|
||||
setTimeout(initScrollAnimations, 100);
|
||||
Reference in New Issue
Block a user