overview / js /main.js
yjernite's picture
yjernite HF Staff
Upload 2 files
a640871 verified
raw
history blame
8.48 kB
// main.js
import { createHomeAreaCard } from './cards/HomeAreaCard.js';
import { createArtifactSummaryCard, createArtifactCarousel } from './cards/ArtifactSummaryCard.js';
import { teamMembers, teamTagData } from './data/team.js';
import { router } from './router.js';
// Team member component
export function createTeamMember(name, role, hfUsername, tags) {
const colors = ['blue', 'green', 'purple', 'orange', 'indigo', 'pink'];
const colorIndex = name.length % colors.length;
const color = colors[colorIndex];
const initials = name.split(' ').map(n => n[0]).join('');
const tagElements = tags.map(tag => {
const tagInfo = teamTagData[tag];
return `<span class="inline-block px-2 py-0.5 text-xs bg-gray-100 text-gray-700 rounded-full hover:bg-blue-100 hover:text-blue-800 cursor-pointer transition-colors whitespace-nowrap" onclick="window.scrollToSection('${tagInfo.id}')">${tagInfo.name}</span>`;
}).join('');
return `
<div class="flex items-start space-x-3 p-3 rounded-lg hover:bg-gray-50 transition-colors">
<div class="flex-shrink-0">
<div class="w-14 h-14 rounded-full overflow-hidden bg-gradient-to-br from-${color}-400 to-${color}-600 flex items-center justify-center relative">
<img
src="images/${hfUsername}.jpeg"
alt="${name}"
class="w-full h-full object-cover"
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
/>
<span class="text-white font-semibold text-base hidden w-full h-full items-center justify-center absolute">${initials}</span>
</div>
</div>
<div class="flex-1 min-w-0">
<h4 class="font-semibold text-gray-900 text-base">
<a href="https://huggingface.co/${hfUsername}" class="hover:text-blue-600 transition-colors" target="_blank">
${name}
</a>
</h4>
<p class="text-sm text-gray-600 mb-1.5">${role}</p>
<div class="flex gap-1.5 overflow-x-auto scrollbar-hide">
${tagElements}
</div>
</div>
</div>
`;
}
// Make router's scrollToSection globally available for onclick handlers
window.scrollToSection = (sectionId) => {
const element = document.getElementById(sectionId);
if (element) {
const elementRect = element.getBoundingClientRect();
const absoluteElementTop = elementRect.top + window.pageYOffset;
const offset = 120; // Account for fixed header + some padding
window.scrollTo({
top: absoluteElementTop - offset,
behavior: 'smooth'
});
}
};
// Scroll to top functionality
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
// Make scrollToTop globally available
window.scrollToTop = scrollToTop;
// Initialize team members
function initializeTeamMembers() {
const teamContainer = document.getElementById('team-grid');
if (!teamContainer) return;
teamContainer.innerHTML = teamMembers.map(member =>
createTeamMember(member.name, member.role, member.username, member.tags)
).join('');
}
// Note: Navigation handling moved to router.js for unified control
// Initialize scroll to top button functionality
function initializeScrollToTop() {
const scrollToTopBtn = document.getElementById('scroll-to-top');
if (!scrollToTopBtn) return;
// Add click event listener
scrollToTopBtn.addEventListener('click', scrollToTop);
// Show/hide button based on scroll position
function toggleScrollToTopButton() {
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
const showThreshold = 300; // Show button after scrolling 300px
if (scrollPosition > showThreshold) {
scrollToTopBtn.classList.remove('opacity-0', 'invisible');
scrollToTopBtn.classList.add('opacity-100', 'visible');
} else {
scrollToTopBtn.classList.remove('opacity-100', 'visible');
scrollToTopBtn.classList.add('opacity-0', 'invisible');
}
}
// Listen for scroll events
window.addEventListener('scroll', toggleScrollToTopButton);
// Initial check
toggleScrollToTopButton();
}
// Main initialization
document.addEventListener('DOMContentLoaded', function() {
// Navigation now handled by router.js
// Initialize scroll to top functionality
initializeScrollToTop();
// The router will handle page-specific component initialization
// No need to call initializeTeamMembers, initializeHomeAreaCards, etc. here
// as they will be called by the router when loading the home page
// Sidebar toggle functionality
const searchToggle = document.getElementById('search-toggle');
const searchSidebar = document.getElementById('search-sidebar');
const searchClose = document.getElementById('search-close');
const mainContent = document.getElementById('main-content');
const overlay = document.getElementById('sidebar-overlay');
// Left sidebar toggle functionality
const sidebarToggle = document.getElementById('sidebar-toggle');
const leftSidebar = document.getElementById('left-sidebar');
const mainContentEl = document.getElementById('main-content');
function toggleLeftSidebar() {
const isOpen = !leftSidebar.classList.contains('-translate-x-full');
if (isOpen) {
// Close sidebar
leftSidebar.classList.add('-translate-x-full');
mainContentEl.style.marginLeft = '0';
} else {
// Open sidebar
leftSidebar.classList.remove('-translate-x-full');
mainContentEl.style.marginLeft = '256px';
}
}
if (sidebarToggle) sidebarToggle.addEventListener('click', toggleLeftSidebar)
function toggleSearch() {
const isOpen = !searchSidebar.classList.contains('translate-x-full');
const leftSidebarOpen = !leftSidebar.classList.contains('-translate-x-full');
if (isOpen) {
searchSidebar.classList.add('translate-x-full');
if (leftSidebarOpen) {
mainContent.style.marginLeft = '256px';
mainContent.classList.remove('mr-80');
} else {
mainContent.style.marginLeft = '0';
mainContent.classList.remove('mr-80');
}
overlay.classList.add('hidden');
} else {
searchSidebar.classList.remove('translate-x-full');
if (leftSidebarOpen) {
mainContent.style.marginLeft = '256px';
mainContent.classList.add('mr-80');
} else {
mainContent.style.marginLeft = '0';
mainContent.classList.add('mr-80');
}
overlay.classList.remove('hidden');
}
}
if (searchToggle) searchToggle.addEventListener('click', toggleSearch);
if (searchClose) searchClose.addEventListener('click', toggleSearch);
if (overlay) overlay.addEventListener('click', toggleSearch);
// Scroll spy for left navigation
const sections = document.querySelectorAll('section[id], div[id]');
const navLinks = document.querySelectorAll('.page-nav-link');
function updateActiveNavigation() {
let current = '';
const scrollPos = window.scrollY + 150;
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.offsetHeight;
if (scrollPos >= sectionTop && scrollPos < sectionTop + sectionHeight) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('text-blue-600', 'bg-blue-50');
link.classList.add('text-gray-700');
if (link.getAttribute('href') === `#${current}`) {
link.classList.remove('text-gray-700');
link.classList.add('text-blue-600', 'bg-blue-50');
}
});
}
window.addEventListener('scroll', updateActiveNavigation);
updateActiveNavigation(); // Initial call
});