Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 65 additions & 24 deletions src/components/Navbar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,70 @@
---

<div class="topnav">
<a href="https://join.slack.com/t/firstcontributors/shared_invite/zt-1n4y7xnk0-DnLVTaN6U9xLU79H5Hi62w" target="_blank" rel="noopener noreferrer">
<img src="/slack.svg" class="logo" alt="slack logo" />
<span>Slack</span>
</a>
<a href="https://www.youtube.com/channel/UCMXNFxCvyH5LhUwEcmY8qGQ" target="_blank" rel="noopener noreferrer">
<img src="/youtube.svg" class="logo" alt="youtube logo" />
<span>Youtube</span>
</a>
<a href="https://twitter.com/1stContribution" target="_blank" rel="noopener noreferrer">
<img src="/twitter.svg" class="logo" alt="twitter logo" />
<span>Twitter</span>
</a>
<a href="https://github.com/firstcontributions/first-contributions" target="_blank" rel="noopener noreferrer">
<img src="/github.svg" class="logo" alt="github logo" />
<span>GitHub</span>
<a href="/" class="brand" aria-label="First Contributions home">
<img src="/favicon.svg" class="brandLogo" alt="" width="28" height="28" />
<span class="brandText">First Contributions</span>
</a>
<div class="navLinks">
<a href="https://join.slack.com/t/firstcontributors/shared_invite/zt-1n4y7xnk0-DnLVTaN6U9xLU79H5Hi62w" target="_blank" rel="noopener noreferrer">
<img src="/slack.svg" class="logo" alt="slack logo" />
<span>Slack</span>
</a>
<a href="https://www.youtube.com/channel/UCMXNFxCvyH5LhUwEcmY8qGQ" target="_blank" rel="noopener noreferrer">
<img src="/youtube.svg" class="logo" alt="youtube logo" />
<span>Youtube</span>
</a>
<a href="https://twitter.com/1stContribution" target="_blank" rel="noopener noreferrer">
<img src="/twitter.svg" class="logo" alt="twitter logo" />
<span>Twitter</span>
</a>
<a href="https://github.com/firstcontributions/first-contributions" target="_blank" rel="noopener noreferrer">
<img src="/github.svg" class="logo" alt="github logo" />
<span>GitHub</span>
</a>
</div>
</div>

<style>
.topnav {
display: flex;
justify-content: center;
justify-content: space-between;
align-items: center;
gap: 2rem;
padding: 1rem;
padding: 0.75rem 1.5rem;
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.topnav a {
.brand {
display: flex;
align-items: center;
gap: 0.5rem;
color: white;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
padding: 0.25rem 0.5rem;
border-radius: 8px;
transition: background-color 0.3s ease;
}

.brand:hover {
background-color: rgba(255, 255, 255, 0.1);
}

.brandLogo {
width: 28px;
height: 28px;
}

.navLinks {
display: flex;
align-items: center;
gap: 1rem;
}

.navLinks a {
display: flex;
align-items: center;
gap: 0.5rem;
Expand All @@ -44,7 +77,7 @@
transition: background-color 0.3s ease;
}

.topnav a:hover {
.navLinks a:hover {
background-color: rgba(255, 255, 255, 0.1);
}

Expand All @@ -55,15 +88,23 @@

@media (max-width: 768px) {
.topnav {
gap: 1rem;
padding: 0.5rem;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
}

.brandText {
display: none;
}

.navLinks {
gap: 0.25rem;
}

.topnav a {
.navLinks a {
padding: 0.25rem 0.5rem;
}

.topnav span {
.navLinks span {
display: none;
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/components/ProjectCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const { projectLink, logoLink, name, description, tags = [], loadIssues = false
<div class="Card-Header">
<img
class="Project-Logo"
alt="the framework or language that the project is build upon"
alt={`${name} logo`}
src={logoLink}
onerror="this.src='/default.png'"
width="60"
Expand Down Expand Up @@ -58,7 +58,6 @@ const { projectLink, logoLink, name, description, tags = [], loadIssues = false
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
height: auto;
min-height: 200px;
margin-bottom: 1.5rem;
position: relative;
}

Expand Down Expand Up @@ -87,7 +86,6 @@ const { projectLink, logoLink, name, description, tags = [], loadIssues = false
}

.Card-Real-Link {
display: block;
text-decoration: none;
color: inherit;
height: 100%;
Expand Down
93 changes: 78 additions & 15 deletions src/components/ProjectList.astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]

<div id="container">
<div class="inputContainer">
<input
id="search"
type="text"
name="search"
placeholder="Search..."
aria-label="Search"
/>
<div class="searchWrapper">
<svg class="searchIcon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input
id="search"
type="text"
name="search"
placeholder="Search..."
aria-label="Search projects"
/>
</div>
</div>
<div id="tag-selector-container" class="inputContainer">
<select id="tag-selector" aria-labelledby="tag-selector-container">
<div class="inputContainer">
<select id="tag-selector" aria-label="Filter by tags">
<option value="">Filter by tags</option>
{allTags.map(tag => (
<option value={tag.toLowerCase()}>{tag}</option>
Expand All @@ -26,6 +32,10 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
</div>
</div>

<div id="results-info" class="resultsInfo">
<span id="results-count"></span>
</div>

<section id="project-list" class="containerLayout">
{projectList.map((item) => (
<ProjectCard
Expand All @@ -39,6 +49,10 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
))}
</section>

<div id="no-results" class="noResults" style="display: none;">
<p>No projects found. Try a different search term or tag.</p>
</div>

<script>
// Get all projects data from the server-rendered content
const projectList = Array.from(document.querySelectorAll('.Card-Container')).map(card => {
Expand Down Expand Up @@ -67,6 +81,8 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
const searchInput = document.getElementById('search');
const tagSelector = document.getElementById('tag-selector');
const projectListContainer = document.getElementById('project-list');
const resultsCount = document.getElementById('results-count');
const noResults = document.getElementById('no-results');

// Filter projects function
function filterProjects() {
Expand Down Expand Up @@ -94,10 +110,23 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
filteredProjects = filtered;

// Hide/show cards instead of re-rendering
let visibleCount = 0;
projectList.forEach(project => {
const isVisible = filteredProjects.includes(project);
project.element.style.display = isVisible ? 'block' : 'none';
if (isVisible) visibleCount++;
});

// Update result count
const totalCount = projectList.length;
if (searchValue.trim() || selectedTags.length > 0) {
resultsCount.textContent = `Showing ${visibleCount} of ${totalCount} projects`;
} else {
resultsCount.textContent = `${totalCount} projects`;
}

// Show/hide no-results message
noResults.style.display = visibleCount === 0 ? 'block' : 'none';
}

// Event listeners
Expand Down Expand Up @@ -133,9 +162,22 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
min-width: 250px;
}

.searchWrapper {
position: relative;
display: flex;
align-items: center;
}

.searchIcon {
position: absolute;
left: 1rem;
color: rgba(255, 255, 255, 0.5);
pointer-events: none;
}

#search {
width: 100%;
padding: 1rem 1.25rem;
padding: 1rem 1.25rem 1rem 2.75rem;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 10px;
background: rgba(255, 255, 255, 0.1);
Expand Down Expand Up @@ -178,11 +220,32 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
color: white;
}

.resultsInfo {
text-align: center;
color: rgba(255, 255, 255, 0.5);
font-size: 0.9rem;
padding: 0 1.5rem 0.5rem;
}

.noResults {
text-align: center;
padding: 3rem 1.5rem;
color: rgba(255, 255, 255, 0.5);
font-size: 1.1rem;
}

.containerLayout {
columns: 3;
column-gap: 1.5rem;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
padding: 2rem 1rem;
break-inside: avoid;
align-items: start;
}

@media (max-width: 980px) {
.containerLayout {
grid-template-columns: repeat(2, 1fr);
}
}


Expand All @@ -204,8 +267,8 @@ const allTags = [...new Set(projectList.flatMap(project => project.tags || []))]
}

.containerLayout {
columns: 1;
column-gap: 1rem;
grid-template-columns: 1fr;
gap: 1rem;
padding: 1rem 0.5rem;
}

Expand Down
16 changes: 16 additions & 0 deletions src/data/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ export const projectList = [
"Python",
],
},
{
name: "ImgTouch",
imageSrc: "https://raw.githubusercontent.com/ParasxAgarwal/imgtouch/main/public/logo.png",
projectLink: "https://github.com/ParasxAgarwal/imgtouch",
description: "AI-powered creative studio for image generation, editing, and enhancement using Google Gemini",
loadIssues: false,
tags: [
"AI",
"React",
"Gemini",
"TypeScript",
"Vite",
"TailwindCSS",
"Image Generation",
],
},
{
name: "CircuitVerse",
imageSrc: "https://avatars.githubusercontent.com/u/42944450?s=200&v=4",
Expand Down