From 7b2566d985578fb2dbf040ae2a9ebaf2199ec351 Mon Sep 17 00:00:00 2001 From: seccodesmith Date: Fri, 23 May 2025 22:19:04 +0200 Subject: [PATCH 1/6] feat: enhance ProjectCard and Projects components with new styles and improved structure style: update opacity in Home styles for better visibility refactor: remove unnecessary comments in Projects component for cleaner code --- src/assets/styles/Home.module.scss | 2 +- src/assets/styles/Project.module.scss | 371 ++++++++++++++++++++++++++ src/components/ProjectCard.tsx | 31 +-- src/pages/Blog.tsx | 2 +- src/pages/Projects.tsx | 12 - 5 files changed, 389 insertions(+), 29 deletions(-) create mode 100644 src/assets/styles/Project.module.scss diff --git a/src/assets/styles/Home.module.scss b/src/assets/styles/Home.module.scss index 14129a5..be74f6f 100644 --- a/src/assets/styles/Home.module.scss +++ b/src/assets/styles/Home.module.scss @@ -73,7 +73,7 @@ color: $accent-fire; font-size: 1rem; animation: fall linear infinite; - opacity: 0.8; + opacity: 0.9; } @keyframes fall { diff --git a/src/assets/styles/Project.module.scss b/src/assets/styles/Project.module.scss new file mode 100644 index 0000000..e4b1c75 --- /dev/null +++ b/src/assets/styles/Project.module.scss @@ -0,0 +1,371 @@ +@use './variables' as *; + +.filterContainer { + margin-bottom: 2rem; +} + +.filterButton { + background-color: rgba(255, 255, 255, 0.05); + border: 1px solid $card-border; + color: $text-ash; + padding: 0.5rem 1rem; + margin: 0 0.25rem 0.5rem; + border-radius: 4px; + transition: all 0.3s ease; +} + +.filterButton:hover, +.filterButton.active { + background-color: rgba(255, 100, 0, 0.1); + border-color: rgba(255, 100, 0, 0.3); + color: $accent-fire; +} + +.filterButton.active { + border-color: $accent-fire; +} + +/* Project Cards */ +.card { + background-color: $card-bg; + border: 1px solid $card-border; + border-radius: 8px; + transition: all 0.3s ease; + margin-bottom: 1.5rem; + overflow: hidden; + height: 100%; +} + +.card:hover { + transform: translateY(-10px); + border-color: rgba(255, 100, 0, 0.3); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); +} + +.cardImg-top { + height: 200px; + object-fit: cover; +} + +.cardTitle { + font-size: 1.5rem; + margin-bottom: 0.75rem; +} + +.cardText { + color: $text-ash; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + line-height: 1.6; + margin-bottom: 1.5rem; +} + +.featuredCard { + position: relative; +} + +.featuredCard .cardImgTop { + height: 300px; +} + +/* Category badges */ +.categoryBadge { + position: absolute; + top: 1rem; + right: 1rem; + background-color: rgba(139, 0, 0, 0.9); + color: $text-light; + padding: 0.25rem 0.75rem; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 1px; + z-index: 1; +} + +.featuredBadge { + position: absolute; + top: 1rem; + left: 1rem; + background: linear-gradient(45deg, $accent-dragon, $accent-fire); + color: $text-light; + padding: 0.25rem 0.75rem; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 1px; + display: flex; + align-items: center; + gap: 5px; + z-index: 1; +} + +/* Tech stack */ +.techTitle { + font-size: 0.9rem; + margin-bottom: 0.625rem; + color: $text-ash; + font-family: 'Fira Code', monospace; +} + +.techStack { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 1.5rem; +} + +.techItem { + display: inline-flex; + align-items: center; + gap: 6px; + background-color: rgba(255, 255, 255, 0.05); + padding: 5px 10px; + border-radius: 4px; + font-size: 0.8rem; + font-family: 'Fira Code', monospace; + color: $text-ash; + transition: all 0.3s ease; +} + +.techItem:hover { + background-color: rgba(255, 100, 0, 0.1); + color: $accent-fire; + transform: translateY(-2px); +} + +.techIcon { + font-size: 1rem; + color: $accent-fire; +} + +/* Project links */ +.btnOutlineSecondary { + background-color: rgba(255, 255, 255, 0.05); + border-color: $card-border; + color: $text-light; +} + +.btnOutlineSecondary:hover { + background-color: rgba(255, 100, 0, 0.1); + border-color: $accent-fire; + color: $text-light; +} + +.btnIcon { + margin-right: 0.5rem; + color: $accent-fire; +} + +/* View All Button */ +.btnPrimary { + background: linear-gradient(45deg, $accent-dragon, $accent-fire); + border: none; + padding: 0.75rem 2rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 1px; + box-shadow: 0 4px 15px rgba(139, 0, 0, 0.3); + transition: all 0.3s ease; +} + +.btnPrimary:hover { + transform: translateY(-3px); + box-shadow: 0 7px 25px rgba(139, 0, 0, 0.5); + background-color: $accent-fire; + background-image: none; +} + +/* Modal Styling */ +.modalContent { + background-color: $card-bg; + border: 1px solid $card-border; + color: $text-light; +} + +.modalHeader { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.modalTitle { + color: $text-light; +} + +.modalFooter { + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +.btnClose { + filter: invert(1) grayscale(100%) brightness(200%); +} + +.featuresList { + padding-left: 1.5rem; + color: $text-ash; +} + +.featuresList li { + margin-bottom: 0.5rem; + position: relative; +} + +.featuresList li::before { + content: "•"; + color: $accent-fire; + position: absolute; + left: -1rem; + top: 0; + font-size: 1.2rem; +} + +.techChip { + display: inline-flex; + align-items: center; + gap: 6px; + background-color: rgba(255, 255, 255, 0.05); + padding: 8px 15px; + border-radius: 20px; + margin-right: 0.5rem; + margin-bottom: 0.5rem; + transition: all 0.3s ease; +} + +.techChip:hover { + background-color: rgba(255, 100, 0, 0.1); + transform: translateY(-3px); +} + +.techChip-icon { + color: $accent-fire; + font-size: 1.1rem; +} + +.techChip-name { + color: $text-ash; + font-size: 0.9rem; + font-family: 'Fira Code', monospace; +} + +.galleryItem { + height: 150px; + border-radius: 8px; + overflow: hidden; + transition: all 0.3s ease; + cursor: pointer; + margin-bottom: 15px; +} + +.galleryItem:hover { + transform: scale(1.05); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); +} + +.galleryImage { + width: 100%; + height: 100%; + object-fit: cover; +} + +/* Binary background effect */ +.binaryLine { + position: absolute; + font-family: 'Fira Code', monospace; + color: $accent-fire; + font-size: 0.8rem; + opacity: 0.15; + pointer-events: none; +} + +/* Ember particle effect */ +.emberParticle { + position: absolute; + width: 3px; + height: 3px; + background-color: $accent-fire; + border-radius: 50%; + opacity: 0.6; + pointer-events: none; + z-index: 2; + box-shadow: 0 0 5px $accent-fire; + animation: float 3s linear infinite; +} + +@keyframes float { + 0% { + transform: translateY(0) rotate(0deg); + opacity: 0.6; + } + + 100% { + transform: translateY(-100px) rotate(360deg); + opacity: 0; + } +} + +/* Footer */ +.footer { + background-color: $primary-dark; + padding: 3rem 0; + border-top: 1px solid rgba(255, 100, 0, 0.2); + margin-top: 3rem; +} + +.socialLinks { + display: flex; + justify-content: center; + gap: 20px; + margin-bottom: 1.5rem; +} + +.socialIcon { + font-size: 1.5rem; + color: $text-ash; + transition: all 0.3s ease; +} + +.socialIcon:hover { + color: $accent-fire; + transform: translateY(-5px); +} + +.copyright { + color: $text-ash; + font-size: 0.9rem; + text-align: center; +} + +/* Responsive adjustments */ +@media (max-width: 992px) { + .pageTitle { + font-size: 2.5rem; + } + + .featuredCard .row { + flex-direction: column; + } +} + +@media (max-width: 768px) { + .pageTitle { + font-size: 2rem; + } + + .techStack { + justify-content: center; + } +} + +@media (max-width: 576px) { + .pageTitle { + font-size: 1.8rem; + } + + .projectLinks { + flex-direction: column; + } + + .projectLinks .btn { + margin-bottom: 0.5rem; + } +} \ No newline at end of file diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index 6a4f293..fc339ca 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -1,5 +1,7 @@ import { useState } from 'react' +import style from '@styles/Project.module.scss' + export interface ProjectTech { name: string; icon: string; @@ -29,41 +31,40 @@ export const ProjectCard: React.FC = ({ project, onOpenDetails return (
setHovered(true)} onMouseLeave={() => setHovered(false)} >
- {project.title} -
{project.category[0]}
- + {project.title} +
{project.category[0]}
{project.featured && ( -
+
Featured
)}
-
-

{project.title}

-

+

+

{project.title}

+

{project.description}

-

// TECHNOLOGIES_USED

-
+

// TECHNOLOGIES_USED

+
{project.technologies.map((tech, index) => ( - + {tech.name} ))}
-
+
{project.links.github && ( - + View Code )} {project.links.demo && ( - + Live Demo diff --git a/src/pages/Blog.tsx b/src/pages/Blog.tsx index 3e6d1be..63e50af 100644 --- a/src/pages/Blog.tsx +++ b/src/pages/Blog.tsx @@ -7,7 +7,7 @@ import style from '@styles/Blog.module.scss'; export const Blog = () => { const [searchQuery, setSearchQuery] = useState(''); - const [currentPage, setCurrentPage] = useState(1); + const [currentPage, /*setCurrentPage*/] = useState(1); const filteredPosts = searchQuery ? blogPostsData.filter(post => diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx index d2e1f0e..faf2fa0 100644 --- a/src/pages/Projects.tsx +++ b/src/pages/Projects.tsx @@ -8,23 +8,18 @@ export const Projects = () => { const [activeFilter, setActiveFilter] = useState('all'); const [selectedProject, setSelectedProject] = useState(null); - // Filter projects based on selected category const filteredProjects = activeFilter === 'all' ? projectsData : projectsData.filter(project => project.category.includes(activeFilter)); - // Get the featured project const featuredProject = projectsData.find(project => project.featured); - // Get regular projects (non-featured) const regularProjects = filteredProjects.filter(project => !project.featured); - // Handle project filter click const handleFilterClick = (filter: string) => { setActiveFilter(filter); }; - // Handle opening project details modal const handleOpenDetails = (id: string) => { const project = projectsData.find(p => p.id === id); if (project) { @@ -32,7 +27,6 @@ export const Projects = () => { } }; - // Handle closing project details modal const handleCloseDetails = () => { setSelectedProject(null); }; @@ -79,16 +73,13 @@ export const Projects = () => {
- {/* Projects Grid */}
- {/* Featured Project */} {featuredProject && (activeFilter === 'all' || featuredProject.category.includes(activeFilter)) && (
)} - {/* Regular Projects */} {regularProjects.map(project => (
@@ -96,14 +87,12 @@ export const Projects = () => { ))}
- {/* No Projects Message */} {filteredProjects.length === 0 && (

No projects found for this category.

)} - {/* View All Button */}
- {/* Project Modal */} {selectedProject && ( )} From bce2276dfa49a06bcfcfa28882a70998c191c199 Mon Sep 17 00:00:00 2001 From: seccodesmith Date: Sat, 24 May 2025 19:31:43 +0200 Subject: [PATCH 2/6] feat: refactor ProjectCard and Projects components for improved category handling and styling --- src/assets/styles/Project.module.scss | 13 +- src/components/ProjectCard.tsx | 189 ++++++++++++++++++-------- src/data/projectsData.ts | 43 +++++- src/pages/Projects.tsx | 84 +++++------- 4 files changed, 215 insertions(+), 114 deletions(-) diff --git a/src/assets/styles/Project.module.scss b/src/assets/styles/Project.module.scss index e4b1c75..d66485a 100644 --- a/src/assets/styles/Project.module.scss +++ b/src/assets/styles/Project.module.scss @@ -42,7 +42,7 @@ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); } -.cardImg-top { +.cardImgTop { height: 200px; object-fit: cover; } @@ -68,10 +68,18 @@ } /* Category badges */ -.categoryBadge { +.categoryBadgeContainer { position: absolute; top: 1rem; right: 1rem; + + display: flex; + flex-direction: row-reverse; + gap: 0.5rem; + z-index: 1; +} + +.categoryBadge { background-color: rgba(139, 0, 0, 0.9); color: $text-light; padding: 0.25rem 0.75rem; @@ -80,7 +88,6 @@ font-weight: 600; text-transform: uppercase; letter-spacing: 1px; - z-index: 1; } .featuredBadge { diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index fc339ca..4d92450 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import React, { useEffect, useState } from 'react' import style from '@styles/Project.module.scss' @@ -12,7 +12,7 @@ export interface ProjectProps { title: string; description: string; image: string; - category: string[]; + category: Category[]; featured?: boolean; technologies: ProjectTech[]; links: { @@ -21,71 +21,146 @@ export interface ProjectProps { }; } +export interface Category { + [key: string]: string; + fullName: string; + shortName: string; + icon: string; +} + interface ProjectCardProps { project: ProjectProps; onOpenDetails: (id: string) => void; } +const ProjectCardTech: React.FC<{ technology: ProjectTech[] }> = ({ technology }) => ( +
+

// TECHNOLOGIES_USED

+
+ {technology.map((tech, index) => ( + + + {tech.name} + + ))} +
+
+) + +const CategoryBadge: React.FC<{ category: Category[] }> = ({ category }) => ( + < div className={style.categoryBadgeContainer} > + { + category.map((cat, index) => ( + + {cat.shortName} + + ))} +
+) + +const ProjectLinks: React.FC<{ links: { github?: string; demo?: string }, id: string, onOpenDetails: (id: string) => void }> = ({ links, id, onOpenDetails }) => ( + +) + export const ProjectCard: React.FC = ({ project, onOpenDetails }) => { const [, setHovered] = useState(false); - - return ( -
setHovered(true)} - onMouseLeave={() => setHovered(false)} - > -
- {project.title} -
{project.category[0]}
- {project.featured && ( -
- - Featured -
- )} -
-
-

{project.title}

-

- {project.description} -

-
-

// TECHNOLOGIES_USED

-
- {project.technologies.map((tech, index) => ( - - - {tech.name} - - ))} + + useEffect(() => { + const createEmbers = () => { + const embersContainer = document.querySelectorAll(`.${style.cardImgTop}`); + + embersContainer.forEach((container) => { + for (let i = 0; i < 5; i++) { + const ember = document.createElement('div'); + ember.className = style.emberParticle; + + ember.style.left = `${Math.random() * 100}%`; + ember.style.bottom = '0'; + ember.style.animationDuration = `${Math.random() * 2 + 3}s`; + ember.style.animationDelay = `${Math.random() * 3}s`; + container.appendChild(ember); + } + }); + }; + createEmbers(); + }, []); + + if (project.featured) { + return ( +
+
setHovered(true)} + onMouseLeave={() => setHovered(false)} + > +
+
+ {project.title} +
+ + Featured +
+ +
+
+
+

{project.title}

+

+ {project.description} +

+ + +
+
-
- - - {project.links.github && ( - - - View Code - - )} - - {project.links.demo && ( - - - Live Demo - - )} +
+ ) + } + + + return ( +
+
setHovered(true)} + onMouseLeave={() => setHovered(false)}> +
+ {project.title} + +
+
+

{project.title}

+

+ {project.description} +

+ +
) -} \ No newline at end of file +}; diff --git a/src/data/projectsData.ts b/src/data/projectsData.ts index 4132324..aa6a8ae 100644 --- a/src/data/projectsData.ts +++ b/src/data/projectsData.ts @@ -1,4 +1,33 @@ -import type { ProjectProps } from "../components/ProjectCard"; +import type { ProjectProps, Category } from "../components/ProjectCard"; + +type CategoryMap = Record +export const Categories: CategoryMap = { + Embedded: { + fullName: "Embedded Systems", + shortName: "Embedded", + icon: "fas fa-microchip", + }, + Web: { + fullName: "Web Development", + shortName: "Web", + icon: "fas fa-code", + }, + ML: { + fullName: "Machine Learning", + shortName: "ML", + icon: "fas fa-robot", + }, + IoT: { + fullName: "Internet of Things", + shortName: "IoT", + icon: "fas fa-network-wired", + }, + Sec: { + fullName: "Cybersecurity", + shortName: "Security", + icon: "fas fa-shield-alt", + }, +} export const projectsData: ProjectProps[] = [ { @@ -6,7 +35,7 @@ export const projectsData: ProjectProps[] = [ title: "ShadowGuardian: Secure IoT Monitoring System", description: "A comprehensive security monitoring system built on STM32 microcontrollers with end-to-end encryption and low-power operation. Integrates with home automation systems and provides real-time alerts through a mobile application.", image: "/images/projects/shadowguardian.jpg", - category: ["iot", "embedded"], + category: [Categories["IoT"], Categories["Embedded"]], featured: true, technologies: [ { name: "C++", icon: "devicon-cplusplus-plain tech-icon" }, @@ -25,7 +54,7 @@ export const projectsData: ProjectProps[] = [ title: "PyroSight: Thermal Anomaly Detection", description: "An intelligent system that uses computer vision and thermal imaging to detect anomalies in industrial equipment. Employs PyTorch for deep learning to predict potential failures before they occur.", image: "/images/projects/pyrosight.jpg", - category: ["ml", "iot"], + category: [Categories["ML"], Categories["IoT"]], technologies: [ { name: "Python", icon: "devicon-python-plain tech-icon" }, { name: "PyTorch", icon: "devicon-pytorch-original tech-icon" }, @@ -41,7 +70,7 @@ export const projectsData: ProjectProps[] = [ title: "NexusFlow: DevOps Dashboard", description: "A real-time monitoring dashboard for DevOps teams that visualizes CI/CD pipelines, infrastructure metrics, and deployment statuses. Built with Blazor for seamless updates without page refreshes.", image: "/images/projects/nexusflow.jpg", - category: ["web"], + category: [Categories["Web"]], technologies: [ { name: "C#", icon: "devicon-csharp-plain tech-icon" }, { name: "Blazor", icon: "devicon-dotnetcore-plain tech-icon" }, @@ -58,7 +87,7 @@ export const projectsData: ProjectProps[] = [ title: "EtherWhisper: Secure Communication Node", description: "A low-power, long-range communication node for IoT networks with military-grade encryption and mesh capabilities. Perfect for remote sensing applications in harsh environments.", image: "/images/projects/etherwhisper.jpg", - category: ["embedded", "iot"], + category: [Categories["Embedded"], Categories["IoT"]], technologies: [ { name: "C", icon: "devicon-c-plain tech-icon" }, { name: "STM32", icon: "fas fa-memory tech-icon" }, @@ -74,7 +103,7 @@ export const projectsData: ProjectProps[] = [ title: "DataForge: Advanced Analytics Platform", description: "A comprehensive data analytics platform with interactive visualization tools and automated reporting features. Integrates with various data sources and provides ML-powered insights.", image: "/images/projects/dataforge.jpg", - category: ["web"], + category: [Categories["Web"]], technologies: [ { name: "Python", icon: "devicon-python-plain tech-icon" }, { name: "Django", icon: "devicon-django-plain tech-icon" }, @@ -91,7 +120,7 @@ export const projectsData: ProjectProps[] = [ title: "VisionKeeper: Object Recognition System", description: "A real-time object recognition system optimized for edge devices. Capable of identifying and tracking objects with high accuracy even in challenging lighting conditions.", image: "/images/projects/visionkeeper.jpg", - category: ["ml"], + category: [Categories["ML"]], technologies: [ { name: "Python", icon: "devicon-python-plain tech-icon" }, { name: "PyTorch", icon: "devicon-pytorch-original tech-icon" }, diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx index faf2fa0..d59354f 100644 --- a/src/pages/Projects.tsx +++ b/src/pages/Projects.tsx @@ -2,88 +2,78 @@ import { useState } from 'react'; import { PageHeader } from '../components/PageHeader'; import { ProjectCard, type ProjectProps } from '../components/ProjectCard'; import { ProjectModal } from '../components/ProjectModal'; -import { projectsData } from '../data/projectsData'; +import { projectsData, Categories } from '../data/projectsData'; +import { styleText } from 'util'; + +import style from '@styles/Project.module.scss' + export const Projects = () => { const [activeFilter, setActiveFilter] = useState('all'); const [selectedProject, setSelectedProject] = useState(null); - - const filteredProjects = activeFilter === 'all' - ? projectsData - : projectsData.filter(project => project.category.includes(activeFilter)); - + + const filteredProjects = activeFilter === 'all' + ? projectsData + : projectsData.filter(project => project.category.some(cat => cat.shortName.toLowerCase() === activeFilter)); + + const categories = Categories; + const featuredProject = projectsData.find(project => project.featured); - + const regularProjects = filteredProjects.filter(project => !project.featured); - + const handleFilterClick = (filter: string) => { setActiveFilter(filter); }; - + const handleOpenDetails = (id: string) => { const project = projectsData.find(p => p.id === id); if (project) { setSelectedProject(project); } }; - + const handleCloseDetails = () => { setSelectedProject(null); }; - + return ( <> - - +
{/* Projects Filter */} -
- - - - - + {Object.values(categories).map((category) => ( + + ))}
- {featuredProject && (activeFilter === 'all' || featuredProject.category.includes(activeFilter)) && ( + {featuredProject && (activeFilter === 'all' || featuredProject.category.some(cat => cat.shortName.toLowerCase() === activeFilter)) && (
)} {regularProjects.map(project => ( -
- -
+ + ))}
@@ -99,7 +89,7 @@ export const Projects = () => {
- + {selectedProject && ( )} From c539be3c871ba8603adfc9930ad8dc7d3ebe55bb Mon Sep 17 00:00:00 2001 From: seccodesmith Date: Sat, 24 May 2025 22:31:34 +0200 Subject: [PATCH 3/6] feat: update BlogCard and Project components with improved styling and structure --- src/components/BlogCard.tsx | 2 +- src/components/ProjectCard.tsx | 4 +- src/components/ProjectModal.tsx | 100 +++++++++++++++++++------------- src/pages/Projects.tsx | 9 ++- 4 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/components/BlogCard.tsx b/src/components/BlogCard.tsx index d9f34bd..c15c786 100644 --- a/src/components/BlogCard.tsx +++ b/src/components/BlogCard.tsx @@ -26,7 +26,7 @@ export const BlogCard: React.FC = ({ post }) => {
{post.title} -
{post.category}
+
{post.category}
{post.featured && (
diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index 4d92450..142c1b0 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -64,13 +64,13 @@ const ProjectLinks: React.FC<{ links: { github?: string; demo?: string }, id: st className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`} onClick={() => onOpenDetails(id)} > - + Project Details {links.github && ( - + View Code )} diff --git a/src/components/ProjectModal.tsx b/src/components/ProjectModal.tsx index 78da803..a3e3330 100644 --- a/src/components/ProjectModal.tsx +++ b/src/components/ProjectModal.tsx @@ -1,5 +1,8 @@ import type { ProjectProps } from './ProjectCard'; +import style from '@styles/Project.module.scss' + + interface ProjectModalProps { project: ProjectProps | null; onClose: () => void; @@ -9,48 +12,65 @@ export const ProjectModal: React.FC = ({ project, onClose }) if (!project) return null; return ( -
-
-
-
-
{project.title}
- -
-
-
- {project.title} + -
-
); } \ No newline at end of file diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx index d59354f..acc020a 100644 --- a/src/pages/Projects.tsx +++ b/src/pages/Projects.tsx @@ -3,7 +3,6 @@ import { PageHeader } from '../components/PageHeader'; import { ProjectCard, type ProjectProps } from '../components/ProjectCard'; import { ProjectModal } from '../components/ProjectModal'; import { projectsData, Categories } from '../data/projectsData'; -import { styleText } from 'util'; import style from '@styles/Project.module.scss' @@ -48,7 +47,7 @@ export const Projects = () => { {/* Projects Filter */}
)} -
- + From 8e2030b0abfa2d53cae83414bee3bbafdbd46dea Mon Sep 17 00:00:00 2001 From: seccodesmith Date: Mon, 26 May 2025 00:06:30 +0200 Subject: [PATCH 4/6] feat: enhance ProjectModal and Projects components by removing unused onClose prop and improving modal styling --- src/components/ProjectCard.tsx | 2 +- src/components/ProjectModal.tsx | 102 ++++++++++++++++++++++++++++---- src/pages/Projects.tsx | 6 +- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index 142c1b0..01a5a48 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -63,7 +63,7 @@ const ProjectLinks: React.FC<{ links: { github?: string; demo?: string }, id: st diff --git a/src/components/ProjectModal.tsx b/src/components/ProjectModal.tsx index a3e3330..6cc4f03 100644 --- a/src/components/ProjectModal.tsx +++ b/src/components/ProjectModal.tsx @@ -5,23 +5,24 @@ import style from '@styles/Project.module.scss' interface ProjectModalProps { project: ProjectProps | null; - onClose: () => void; } -export const ProjectModal: React.FC = ({ project, onClose }) => { +export const ProjectModal: React.FC = ({ project }) => { if (!project) return null; return (