Spaces:
Running
Running
File size: 3,907 Bytes
f323371 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
document.addEventListener('DOMContentLoaded', () => {
// --- Intersection Observer for Scroll Animations ---
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0.1
};
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
// Stop observing once visible
observer.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.fade-in-section').forEach(section => {
observer.observe(section);
});
// --- Populate Skills Dynamically ---
const skills = [
{ name: "JavaScript", level: "Expert" },
{ name: "React.js", level: "Advanced" },
{ name: "Tailwind CSS", level: "Expert" },
{ name: "Node.js", level: "Intermediate" },
{ name: "TypeScript", level: "Advanced" },
{ name: "UI/UX Design", level: "Advanced" },
{ name: "HTML5 & CSS3", level: "Expert" },
{ name: "Git & GitHub", level: "Advanced" },
{ name: "Python", level: "Intermediate" },
{ name: "SQL", level: "Intermediate" },
];
const skillsContainer = document.getElementById('skills-container');
if(skillsContainer) {
skills.forEach(skill => {
const badge = document.createElement('div');
// Styling the badge manually to ensure it matches the design without creating a new component
badge.className = `
group relative px-6 py-4 bg-surface/40 border border-white/5
rounded-xl hover:border-primary/50 hover:bg-surface/80
transition-all duration-300 cursor-default
`;
badge.innerHTML = `
<div class="flex items-center gap-3">
<div class="w-2 h-2 rounded-full bg-secondary group-hover:bg-primary transition-colors"></div>
<span class="font-medium text-slate-200 group-hover:text-white">${skill.name}</span>
</div>
<div class="text-xs text-slate-500 mt-1 pl-5 font-mono">${skill.level}</div>
`;
skillsContainer.appendChild(badge);
});
}
// --- Fetch Real Data from GitHub (Optional Enhancement) ---
// This section tries to fetch real repos but falls back if it fails (e.g., rate limits)
async function fetchGitHubRepos() {
const projectGrid = document.getElementById('projects-grid');
if(!projectGrid) return;
try {
const response = await fetch('https://api.github.com/users/kimyg119/repos?sort=updated&per_page=6');
if (!response.ok) throw new Error('API limit or error');
const repos = await response.json();
// Keep the static ones, maybe add to them or replace.
// Let's create new web component elements dynamically
repos.forEach((repo, index) => {
if(index > 2) return; // Just adding a couple for demo to not clutter
const card = document.createElement('custom-project-card');
card.setAttribute('title', repo.name);
card.setAttribute('desc', repo.description || 'No description provided.');
// Use a random tech image
card.setAttribute('image', `http://static.photos/technology/640x360/${repo.id % 100}`);
card.setAttribute('tags', repo.language || 'Code');
card.setAttribute('link', repo.html_url);
projectGrid.appendChild(card);
});
} catch (error) {
console.log('Using static projects due to API limits or error.');
}
}
fetchGitHubRepos();
}); |