Skip to content

Commit 028abbf

Browse files
committed
Update Portfolio
1 parent 5f02b8f commit 028abbf

8 files changed

Lines changed: 462 additions & 120 deletions

File tree

package-lock.json

Lines changed: 377 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"preview": "astro preview"
99
},
1010
"dependencies": {
11-
"astro": "^4.16.0"
11+
"astro": "^4.16.0",
12+
"sass": "^1.101.0"
1213
}
1314
}

src/components/About.astro

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,16 @@
2020
</div>
2121
</div>
2222

23-
<p class="about-headline">
24-
<span><i class="fa-solid fa-code" aria-hidden="true"></i>Building scalable web apps</span>
25-
<span class="about-headline__sep">|</span>
26-
<span><i class="fa-solid fa-layer-group" aria-hidden="true"></i>MERN / MEAN Stack</span>
27-
</p>
28-
2923
<p class="about-bio">
3024
Passionate Full Stack Developer with expertise in building efficient, scalable web
3125
applications using modern technologies like React, Angular, Node.js, MongoDB, and MySQL.
3226
</p>
3327

34-
<div class="about-quickfacts">
35-
<span class="about-qf-chip"><i class="fa-solid fa-calendar" aria-hidden="true"></i>2+ Years Exp</span>
36-
<span class="about-qf-chip"><i class="fa-solid fa-briefcase" aria-hidden="true"></i>Full Time</span>
37-
<span class="about-qf-chip"><i class="fa-solid fa-location-dot" aria-hidden="true"></i>Kerala, India</span>
38-
<span class="about-qf-chip about-qf-chip--active"><span class="about-qf-dot" aria-hidden="true"></span>Open to Work</span>
39-
</div>
40-
4128
<div class="about-stats-strip">
29+
<div class="stat-card anim">
30+
<span class="stat-val"><span class="stat-num" data-target="2">0</span><span class="stat-suffix">+</span></span>
31+
<span class="stat-label">years exp</span>
32+
</div>
4233
<div class="stat-card anim">
4334
<span class="stat-val"><span class="stat-num" id="about-projects-stat" data-target="12">0</span><span class="stat-suffix">+</span></span>
4435
<span class="stat-label">projects</span>
@@ -47,10 +38,6 @@
4738
<span class="stat-val"><span class="stat-num" data-target="10">0</span><span class="stat-suffix">+</span></span>
4839
<span class="stat-label">technologies</span>
4940
</div>
50-
<div class="stat-card anim">
51-
<span class="stat-val"><span class="stat-num" data-target="100">0</span><span class="stat-suffix">+</span></span>
52-
<span class="stat-label">bugs fixed</span>
53-
</div>
5441
</div>
5542

5643
<div class="about-cta">

src/components/common/DotNav.astro

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<nav class="dot-nav" aria-label="Section navigation">
2+
<button class="dot-nav__btn active" data-section="about" aria-label="Go to About" aria-current="location"></button>
3+
<button class="dot-nav__btn" data-section="skills" aria-label="Go to Skills"></button>
4+
<button class="dot-nav__btn" data-section="experience" aria-label="Go to Experience"></button>
5+
<button class="dot-nav__btn" data-section="projects" aria-label="Go to Projects"></button>
6+
<button class="dot-nav__btn github-mobile-dot" data-section="github" aria-label="Go to GitHub"></button>
7+
<button class="dot-nav__btn" data-section="education" aria-label="Go to Education"></button>
8+
<button class="dot-nav__btn" data-section="contact" aria-label="Go to Contact"></button>
9+
</nav>

src/components/common/Footer.astro

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<footer class="site-footer" aria-label="Site footer">
2+
&copy; <span id="footer-year"></span> Muhammed Rashid
3+
</footer>
4+
5+
<button id="back-top-btn" type="button" aria-label="Back to top" class="outline-btn back-top-btn">
6+
<i class="fa-solid fa-arrow-up"></i>
7+
</button>
8+
9+
<script>
10+
const yearEl = document.getElementById('footer-year');
11+
if (yearEl) yearEl.textContent = String(new Date().getFullYear());
12+
</script>

src/components/common/Header.astro

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<header class="site-header">
2+
<div class="header-logo">
3+
<img src="/assets/images/profile.webp" alt="" aria-hidden="true" width="28" height="28" class="header-avatar" />
4+
<span class="about-qf-chip about-qf-chip--active"><span class="about-qf-dot" aria-hidden="true"></span>Open to Work</span>
5+
</div>
6+
<div class="header-end">
7+
<button id="theme-toggle" type="button" class="outline-btn" aria-label="Switch to light theme">
8+
<i class="fa-solid fa-sun"></i>
9+
</button>
10+
<span id="theme-announce" class="sr-only" aria-live="polite"></span>
11+
<a href="/resume.pdf" target="_blank" rel="noreferrer" class="filled-btn" aria-label="Download resume">
12+
<i class="fa-solid fa-download"></i><span>resume</span>
13+
</a>
14+
</div>
15+
<div id="scroll-progress" class="header-progress" aria-hidden="true"></div>
16+
</header>
17+
18+
<script>
19+
const THEME_KEY = 'theme';
20+
21+
function applyTheme(theme: string): void {
22+
document.documentElement.dataset.theme = theme;
23+
const btn = document.getElementById('theme-toggle');
24+
const icon = btn?.querySelector('i');
25+
const announce = document.getElementById('theme-announce');
26+
if (icon) icon.className = theme === 'dark' ? 'fa-solid fa-sun' : 'fa-solid fa-moon';
27+
if (btn) btn.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`);
28+
if (announce) announce.textContent = `${theme} mode enabled`;
29+
localStorage.setItem(THEME_KEY, theme);
30+
}
31+
32+
const stored = localStorage.getItem(THEME_KEY);
33+
applyTheme(
34+
stored === 'dark' || stored === 'light' ? stored
35+
: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
36+
);
37+
38+
let debounceTimer: ReturnType<typeof setTimeout>;
39+
document.getElementById('theme-toggle')?.addEventListener('click', () => {
40+
clearTimeout(debounceTimer);
41+
debounceTimer = setTimeout(() => {
42+
applyTheme(document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark');
43+
}, 200);
44+
});
45+
</script>

src/layouts/BaseLayout.astro

Lines changed: 13 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
---
2-
import '../styles/global.css';
2+
import '../styles/global.scss';
3+
import Header from '../components/common/Header.astro';
4+
import Footer from '../components/common/Footer.astro';
5+
import DotNav from '../components/common/DotNav.astro';
36
47
interface Props {
58
title?: string;
@@ -20,13 +23,13 @@ const {
2023

2124
<title>{title}</title>
2225
<meta name="description" content={description} />
23-
<meta name="author" content="Muhammed Rashid" />
24-
<meta name="robots" content="index, follow" />
26+
<meta name="author" content="Muhammed Rashid" />
27+
<meta name="robots" content="index, follow" />
2528

2629
<link rel="canonical" href="https://devmdrd.github.io/" />
2730

2831
<meta name="theme-color" content="#000000" media="(prefers-color-scheme: dark)" />
29-
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
32+
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
3033

3134
<meta property="og:type" content="website" />
3235
<meta property="og:site_name" content="Muhammed Rashid Portfolio" />
@@ -86,14 +89,13 @@ const {
8689
(function () {
8790
var s = localStorage.getItem('theme');
8891
document.documentElement.dataset.theme =
89-
(s === 'dark' || s === 'light') ? s
90-
: (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
92+
s === 'dark' || s === 'light' ? s
93+
: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
9194
}());
9295
</script>
9396
</head>
9497

9598
<body>
96-
9799
<a href="#about" class="skip-link">Skip to main content</a>
98100

99101
<div id="loader" class="loader" role="status" aria-label="Loading portfolio">
@@ -106,83 +108,19 @@ const {
106108
<p class="loader__user">@devmdrd</p>
107109
</div>
108110

109-
<nav class="dot-nav" aria-label="Section navigation">
110-
<button class="dot-nav__btn active" data-section="about" aria-label="Go to About" aria-current="location"></button>
111-
<button class="dot-nav__btn" data-section="skills" aria-label="Go to Skills"></button>
112-
<button class="dot-nav__btn" data-section="experience" aria-label="Go to Experience"></button>
113-
<button class="dot-nav__btn" data-section="projects" aria-label="Go to Projects"></button>
114-
<button class="dot-nav__btn github-mobile-dot" data-section="github" aria-label="Go to GitHub"></button>
115-
<button class="dot-nav__btn" data-section="education" aria-label="Go to Education"></button>
116-
<button class="dot-nav__btn" data-section="contact" aria-label="Go to Contact"></button>
117-
</nav>
118-
119-
<header class="site-header">
120-
<div class="header-logo">
121-
<img src="/assets/images/profile.webp" alt="" aria-hidden="true" width="28" height="28" class="header-avatar" />
122-
devmdrd
123-
</div>
124-
<div class="header-end">
125-
<button id="theme-toggle" type="button" class="outline-btn" aria-label="Switch to light theme">
126-
<i class="fa-solid fa-sun"></i>
127-
</button>
128-
<span id="theme-announce" class="sr-only" aria-live="polite"></span>
129-
<a href="/resume.pdf" target="_blank" rel="noreferrer" class="filled-btn" aria-label="Download resume">
130-
<i class="fa-solid fa-download"></i><span>resume</span>
131-
</a>
132-
</div>
133-
<div id="scroll-progress" class="header-progress" aria-hidden="true"></div>
134-
</header>
111+
<DotNav />
112+
<Header />
135113

136114
<main class="main-content">
137115
<slot />
138116
</main>
139117

140-
<footer class="site-footer" aria-label="Site footer">
141-
&copy; <span id="footer-year"></span> Muhammed Rashid
142-
</footer>
143-
144-
<button id="back-top-btn" type="button" aria-label="Back to top" class="outline-btn back-top-btn">
145-
<i class="fa-solid fa-arrow-up"></i>
146-
</button>
118+
<Footer />
147119

148120
<script defer src="https://cdn.jsdelivr.net/npm/typed.js@2.1.0/dist/typed.umd.js"></script>
149121
<script defer src="https://cdn.jsdelivr.net/npm/countup.js@2.8.0/dist/countUp.umd.js"></script>
150122

151123
<script>
152-
const yearEl = document.getElementById('footer-year');
153-
if (yearEl) yearEl.textContent = String(new Date().getFullYear());
154-
155-
const THEME_KEY = 'theme';
156-
157-
function getTheme(): string {
158-
return document.documentElement.dataset.theme ?? 'dark';
159-
}
160-
161-
function debounce(fn: () => void, ms: number) {
162-
let timer: ReturnType<typeof setTimeout>;
163-
return () => { clearTimeout(timer); timer = setTimeout(fn, ms); };
164-
}
165-
166-
function applyTheme(theme: string): void {
167-
document.documentElement.dataset.theme = theme;
168-
const btn = document.getElementById('theme-toggle');
169-
const icon = btn?.querySelector('i');
170-
const announce = document.getElementById('theme-announce');
171-
if (icon) icon.className = theme === 'dark' ? 'fa-solid fa-sun' : 'fa-solid fa-moon';
172-
if (btn) btn.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`);
173-
if (announce) announce.textContent = `${theme} mode enabled`;
174-
localStorage.setItem(THEME_KEY, theme);
175-
}
176-
177-
const stored = localStorage.getItem(THEME_KEY);
178-
const initial = (stored === 'dark' || stored === 'light') ? stored
179-
: (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
180-
applyTheme(initial);
181-
182-
document.getElementById('theme-toggle')?.addEventListener('click', debounce(() => {
183-
applyTheme(getTheme() === 'dark' ? 'light' : 'dark');
184-
}, 200));
185-
186124
const LAST_SECTION_KEY = 'lastSection';
187125
const sections = Array.from(document.querySelectorAll<HTMLElement>('section[id]'));
188126
const total = sections.length;
@@ -223,8 +161,7 @@ const {
223161

224162
document.querySelectorAll<HTMLElement>('.dot-nav__btn[data-section]').forEach(btn => {
225163
btn.addEventListener('click', () => {
226-
const s = document.getElementById(btn.dataset.section!);
227-
if (s) s.scrollIntoView({ behavior: 'smooth' });
164+
document.getElementById(btn.dataset.section!)?.scrollIntoView({ behavior: 'smooth' });
228165
});
229166
});
230167

@@ -248,6 +185,5 @@ const {
248185
document.dispatchEvent(new CustomEvent('portfolio:ready'));
249186
}
250187
</script>
251-
252188
</body>
253189
</html>
Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -576,30 +576,6 @@ hr {
576576
.about-intro .fa-angle-right { margin-right: 0.25rem; }
577577

578578

579-
580-
.about-headline {
581-
margin: 0 0 0.75rem;
582-
display: flex;
583-
flex-wrap: wrap;
584-
align-items: center;
585-
gap: 0.4rem 0.5rem;
586-
font-size: var(--fs-sm);
587-
color: var(--fg-secondary);
588-
}
589-
590-
.about-headline span { display: inline-flex; align-items: center; gap: 0.35rem; }
591-
592-
.about-headline__sep { color: var(--border); font-weight: 300; }
593-
594-
.about-headline i { font-size: 0.65rem; color: var(--fg-secondary); }
595-
596-
.about-quickfacts {
597-
display: flex;
598-
flex-wrap: wrap;
599-
gap: 0.4rem;
600-
margin-bottom: 1.25rem;
601-
}
602-
603579
.about-qf-chip {
604580
display: inline-flex;
605581
align-items: center;

0 commit comments

Comments
 (0)