Skip to content

Commit ddbe36e

Browse files
committed
feat: Relocate external projects section from Footer to ModuleHub and update ModuleHub's no results icon.
1 parent 4d59779 commit ddbe36e

File tree

4 files changed

+152
-135
lines changed

4 files changed

+152
-135
lines changed

src/components/Hub/ModuleHub.module.css

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,82 @@
129129
color: var(--color-text-muted);
130130
font-size: var(--text-sm);
131131
margin-top: var(--space-8);
132+
}
133+
134+
/* External Projects Section */
135+
.externalSection {
136+
margin-top: var(--space-12);
137+
padding-top: var(--space-8);
138+
border-top: 1px solid var(--color-border-default);
139+
}
140+
141+
.externalTitle {
142+
display: flex;
143+
align-items: center;
144+
gap: var(--space-2);
145+
font-size: var(--text-lg);
146+
font-weight: 700;
147+
color: var(--color-text-primary);
148+
margin-bottom: var(--space-6);
149+
}
150+
151+
.externalTitle svg {
152+
color: var(--color-text-muted);
153+
}
154+
155+
.externalGrid {
156+
display: grid;
157+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
158+
gap: var(--space-4);
159+
}
160+
161+
.externalCard {
162+
display: flex;
163+
align-items: center;
164+
gap: var(--space-3);
165+
padding: var(--space-4);
166+
background: linear-gradient(145deg, #1e293b, #0f172a);
167+
border: 1px solid var(--color-border-default);
168+
border-radius: var(--radius-lg);
169+
text-decoration: none;
170+
transition: all 0.2s ease;
171+
}
172+
173+
.externalCard:hover {
174+
border-color: var(--accent);
175+
transform: translateY(-2px);
176+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
177+
}
178+
179+
.externalIndicator {
180+
width: 8px;
181+
height: 8px;
182+
border-radius: 50%;
183+
flex-shrink: 0;
184+
}
185+
186+
.externalInfo {
187+
flex: 1;
188+
}
189+
190+
.externalInfo h4 {
191+
margin: 0 0 var(--space-1) 0;
192+
font-size: var(--text-sm);
193+
font-weight: 600;
194+
color: var(--color-text-primary);
195+
}
196+
197+
.externalInfo p {
198+
margin: 0;
199+
font-size: var(--text-xs);
200+
color: var(--color-text-muted);
201+
}
202+
203+
.externalIcon {
204+
color: var(--color-text-muted);
205+
transition: color 0.2s;
206+
}
207+
208+
.externalCard:hover .externalIcon {
209+
color: var(--accent);
132210
}

src/components/Hub/ModuleHub.tsx

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,40 @@ import { useNavigation, useSearch } from '../../contexts';
88
import { MODULE_REGISTRY } from '../../types';
99
import styles from './ModuleHub.module.css';
1010

11+
interface ExternalProject {
12+
title: string;
13+
description: string;
14+
url: string;
15+
color: string;
16+
}
17+
18+
const externalProjects: ExternalProject[] = [
19+
{
20+
title: 'Microservices Architecture',
21+
description: 'Complete Spring Boot microservices implementation',
22+
url: 'https://pramithamj.github.io/fully-completed-microservices-Java-Springboot/',
23+
color: '#86efac',
24+
},
25+
{
26+
title: 'Art of Software Design',
27+
description: 'Design patterns and architectural principles',
28+
url: 'https://pramithamj.github.io/art-of-software-design/',
29+
color: '#a855f7',
30+
},
31+
{
32+
title: 'Thread Lifecycle Visualizer',
33+
description: 'Interactive thread state visualization',
34+
url: 'https://pramithamj.github.io/thread-lifecycle-visualizer/',
35+
color: '#fcd34d',
36+
},
37+
{
38+
title: 'CPU Scheduling Visualizer',
39+
description: 'OS scheduling algorithms visualization',
40+
url: 'https://pramithamj.github.io/cpu-scheduling-visualizer/',
41+
color: '#60a5fa',
42+
},
43+
];
44+
1145
export function ModuleHub() {
1246
const { navigateTo } = useNavigation();
1347
const { searchQuery, filterBadge } = useSearch();
@@ -41,7 +75,12 @@ export function ModuleHub() {
4175

4276
{filteredModules.length === 0 ? (
4377
<div className={styles.noResults}>
44-
<span className={styles.noResultsIcon}>🔍</span>
78+
<span className={styles.noResultsIcon}>
79+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="48" height="48">
80+
<circle cx="11" cy="11" r="8" />
81+
<path d="m21 21-4.35-4.35" />
82+
</svg>
83+
</span>
4584
<p>No modules found matching your search.</p>
4685
<p className={styles.noResultsHint}>Try a different search term or filter.</p>
4786
</div>
@@ -81,7 +120,39 @@ export function ModuleHub() {
81120
<p className={styles.moduleCount}>
82121
Showing {filteredModules.length} of {allModules.length} modules
83122
</p>
123+
124+
{/* External Projects Section */}
125+
<div className={styles.externalSection}>
126+
<h3 className={styles.externalTitle}>
127+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="20" height="20">
128+
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3" strokeLinecap="round" strokeLinejoin="round" />
129+
</svg>
130+
Related Projects
131+
</h3>
132+
<div className={styles.externalGrid}>
133+
{externalProjects.map((project) => (
134+
<a
135+
key={project.title}
136+
href={project.url}
137+
target="_blank"
138+
rel="noopener noreferrer"
139+
className={styles.externalCard}
140+
style={{ '--accent': project.color } as React.CSSProperties}
141+
>
142+
<div className={styles.externalIndicator} style={{ backgroundColor: project.color }} />
143+
<div className={styles.externalInfo}>
144+
<h4>{project.title}</h4>
145+
<p>{project.description}</p>
146+
</div>
147+
<svg className={styles.externalIcon} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="16" height="16">
148+
<path d="M7 17L17 7M17 7H7M17 7V17" strokeLinecap="round" strokeLinejoin="round" />
149+
</svg>
150+
</a>
151+
))}
152+
</div>
153+
</div>
84154
</div>
85155
</div>
86156
);
87157
}
158+

src/components/Layout/Footer.module.css

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,83 +3,12 @@
33
.footer {
44
background-color: var(--color-bg-secondary);
55
border-top: 1px solid var(--color-border-default);
6-
margin-top: auto;
7-
}
8-
9-
/* Projects Section */
10-
.projectsSection {
11-
max-width: 1200px;
12-
margin: 0 auto;
13-
padding: var(--space-8) var(--space-6);
14-
border-bottom: 1px solid var(--color-border-default);
15-
}
16-
17-
.sectionTitle {
18-
text-align: center;
19-
font-size: var(--text-lg);
20-
font-weight: 700;
21-
color: var(--color-text-primary);
22-
margin-bottom: var(--space-6);
23-
}
24-
25-
.projectsGrid {
26-
display: grid;
27-
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
28-
gap: var(--space-4);
29-
}
30-
31-
.projectCard {
32-
display: flex;
33-
align-items: center;
34-
gap: var(--space-3);
35-
padding: var(--space-4);
36-
background-color: rgba(255, 255, 255, 0.03);
37-
border: 1px solid var(--color-border-default);
38-
border-radius: var(--radius-lg);
39-
text-decoration: none;
40-
transition: all 0.2s ease;
41-
}
42-
43-
.projectCard:hover {
44-
border-color: var(--accent);
45-
background-color: rgba(255, 255, 255, 0.05);
46-
transform: translateY(-2px);
47-
}
48-
49-
.projectIcon {
50-
width: 40px;
51-
height: 40px;
52-
background-color: rgba(255, 255, 255, 0.05);
53-
border-radius: var(--radius-md);
54-
display: flex;
55-
align-items: center;
56-
justify-content: center;
57-
flex-shrink: 0;
58-
}
59-
60-
.projectIcon svg {
61-
width: 20px;
62-
height: 20px;
63-
color: var(--accent);
64-
}
65-
66-
.projectInfo h4 {
67-
margin: 0 0 var(--space-1) 0;
68-
font-size: var(--text-sm);
69-
font-weight: 600;
70-
color: var(--color-text-primary);
71-
}
72-
73-
.projectInfo p {
74-
margin: 0;
75-
font-size: var(--text-xs);
76-
color: var(--color-text-muted);
6+
padding: var(--space-6);
777
}
788

799
/* Social Section */
8010
.socialSection {
8111
text-align: center;
82-
padding: var(--space-6);
8312
}
8413

8514
.socialLinks {

src/components/Layout/Footer.tsx

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Footer Component
3-
* Social links and external resources
3+
* Social links and copyright
44
*/
55

66
import styles from './Footer.module.css';
@@ -77,70 +77,9 @@ const socialLinks: SocialLink[] = [
7777
},
7878
];
7979

80-
interface ExternalProject {
81-
title: string;
82-
description: string;
83-
url: string;
84-
color: string;
85-
}
86-
87-
const externalProjects: ExternalProject[] = [
88-
{
89-
title: 'Microservices Architecture',
90-
description: 'Complete Spring Boot microservices implementation',
91-
url: 'https://pramithamj.github.io/fully-completed-microservices-Java-Springboot/',
92-
color: '#86efac',
93-
},
94-
{
95-
title: 'Art of Software Design',
96-
description: 'Design patterns and architectural principles',
97-
url: 'https://pramithamj.github.io/art-of-software-design/',
98-
color: '#a855f7',
99-
},
100-
{
101-
title: 'Thread Lifecycle Visualizer',
102-
description: 'Interactive thread state visualization',
103-
url: 'https://pramithamj.github.io/thread-lifecycle-visualizer/',
104-
color: '#fcd34d',
105-
},
106-
{
107-
title: 'CPU Scheduling Visualizer',
108-
description: 'OS scheduling algorithms visualization',
109-
url: 'https://pramithamj.github.io/cpu-scheduling-visualizer/',
110-
color: '#60a5fa',
111-
},
112-
];
113-
11480
export function Footer() {
11581
return (
11682
<footer className={styles.footer}>
117-
{/* External Projects */}
118-
<section className={styles.projectsSection}>
119-
<h3 className={styles.sectionTitle}>Related Projects</h3>
120-
<div className={styles.projectsGrid}>
121-
{externalProjects.map((project) => (
122-
<a
123-
key={project.title}
124-
href={project.url}
125-
target="_blank"
126-
rel="noopener noreferrer"
127-
className={styles.projectCard}
128-
style={{ '--accent': project.color } as React.CSSProperties}
129-
>
130-
<div className={styles.projectIcon}>
131-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
132-
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3" strokeLinecap="round" strokeLinejoin="round" />
133-
</svg>
134-
</div>
135-
<div className={styles.projectInfo}>
136-
<h4>{project.title}</h4>
137-
<p>{project.description}</p>
138-
</div>
139-
</a>
140-
))}
141-
</div>
142-
</section>
143-
14483
{/* Social Links */}
14584
<div className={styles.socialSection}>
14685
<div className={styles.socialLinks}>

0 commit comments

Comments
 (0)