Skip to content

Commit 2b60f9c

Browse files
Merge pull request #62 from ThomasJButler/v3.5-DependencyUpdate
V3.5 dependency update
2 parents 34e3dbf + 7900521 commit 2b60f9c

11 files changed

Lines changed: 201 additions & 115 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ Thumbs.db
2727
*.log
2828
*.tmp
2929
*.temp
30+
31+
# Playwright
32+
/playwright-screenshots
33+
/playwright-report
34+
/playwright-artifacts
35+
/test-results

e2e/screenshots.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { test } from '@playwright/test';
2+
import path from 'path';
3+
4+
const pages = [
5+
{ name: 'home', route: '/' },
6+
{ name: 'about', route: '/about' },
7+
{ name: 'projects', route: '/projects' },
8+
{ name: 'services', route: '/services' },
9+
{ name: 'contact', route: '/contact' },
10+
{ name: 'sitemap', route: '/sitemap' },
11+
{ name: 'updates', route: '/updates' },
12+
];
13+
14+
const screenshotDir = path.join(__dirname, '..', 'playwright-screenshots');
15+
16+
for (const pg of pages) {
17+
test(`screenshot: ${pg.name}`, async ({ page, browserName }, testInfo) => {
18+
const viewport = testInfo.project.name.includes('iPhone') ? 'mobile' : 'desktop';
19+
20+
// The app loads from /react.html and uses ?redirect= for client-side routing
21+
const url = pg.route === '/'
22+
? '/react.html'
23+
: `/react.html?redirect=${pg.route}`;
24+
25+
await page.goto(url, { waitUntil: 'networkidle' });
26+
// Allow animations and lazy-loaded content to settle
27+
await page.waitForTimeout(3000);
28+
29+
await page.screenshot({
30+
path: path.join(screenshotDir, `${pg.name}-${viewport}-${browserName}.png`),
31+
fullPage: true,
32+
});
33+
});
34+
}

package-lock.json

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
"test": "vitest",
3838
"test:ui": "vitest --ui",
3939
"test:coverage": "vitest --coverage",
40+
"test:e2e": "npx playwright test",
41+
"test:screenshots": "npx playwright test e2e/screenshots.spec.ts",
4042
"update": "node scripts/portfolio-update.js",
4143
"update:quick": "echo '$(date): Quick update' >> devlog.md && git add . && git commit -m 'Portfolio: Quick update' && git push",
4244
"update:stats": "node scripts/generate-stats.js"
@@ -46,6 +48,7 @@
4648
"license": "ISC",
4749
"devDependencies": {
4850
"@eslint/js": "^9.31.0",
51+
"@playwright/test": "^1.58.2",
4952
"@testing-library/jest-dom": "^6.6.3",
5053
"@testing-library/react": "^16.3.0",
5154
"@testing-library/user-event": "^14.6.1",

playwright.config.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
export default defineConfig({
4+
testDir: './e2e',
5+
fullyParallel: true,
6+
forbidOnly: !!process.env.CI,
7+
retries: 0,
8+
workers: 1,
9+
reporter: 'html',
10+
use: {
11+
baseURL: 'http://localhost:4173',
12+
screenshot: 'off', // We take screenshots manually in tests
13+
},
14+
projects: [
15+
{
16+
name: 'Desktop Chrome',
17+
use: { ...devices['Desktop Chrome'] },
18+
},
19+
{
20+
name: 'Desktop Firefox',
21+
use: { ...devices['Desktop Firefox'] },
22+
},
23+
{
24+
name: 'Desktop Safari',
25+
use: { ...devices['Desktop Safari'] },
26+
},
27+
{
28+
name: 'iPhone 14',
29+
use: { ...devices['iPhone 14'] },
30+
},
31+
],
32+
webServer: {
33+
command: 'npm run build && npm run preview -- --port 4173',
34+
url: 'http://localhost:4173',
35+
reuseExistingServer: !process.env.CI,
36+
timeout: 60000,
37+
},
38+
});

src/components/Header.module.css

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@
88
left: 0;
99
right: 0;
1010
z-index: 1000;
11-
background: rgba(0, 0, 0, 0.95);
12-
backdrop-filter: blur(10px);
13-
-webkit-backdrop-filter: blur(10px);
14-
border-bottom: 1px solid var(--matrix-green, #00ff00);
11+
background: #000000;
12+
border-bottom: 1px solid rgba(0, 255, 0, 0.2);
1513
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1614
}
1715

1816
.siteHeader.scrolled {
19-
background: rgba(0, 0, 0, 0.98);
20-
box-shadow: 0 2px 20px rgba(0, 255, 0, 0.1);
17+
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.5);
18+
border-bottom-color: rgba(0, 255, 0, 0.3);
2119
}
2220

2321
.container {
@@ -161,16 +159,16 @@
161159
.nav {
162160
display: flex;
163161
align-items: center;
164-
gap: 2.5rem; /* Increased for better spacing after header name */
165-
margin-left: 1rem; /* Shift right to accommodate // symbols */
162+
gap: 1.5rem;
166163
}
167164

168165
.navList {
169166
display: flex;
170167
list-style: none;
171168
margin: 0;
172169
padding: 0;
173-
gap: 2rem;
170+
gap: 1.5rem;
171+
align-items: center;
174172
}
175173

176174
.navItem {
@@ -186,13 +184,13 @@
186184

187185
.navLink {
188186
font-family: var(--font-body);
189-
font-size: 0.75rem; /* Reduced from 0.875rem */
190-
color: rgba(0, 255, 0, 0.7);
187+
font-size: 0.8rem;
188+
color: rgba(255, 255, 255, 0.6);
191189
text-decoration: none;
192190
text-transform: uppercase;
193-
letter-spacing: 0.1em;
194-
padding: 0.5rem 0.75rem;
195-
transition: color 0.3s ease, text-shadow 0.3s ease;
191+
letter-spacing: 0.12em;
192+
padding: 0.4rem 0;
193+
transition: color 0.3s ease;
196194
display: flex;
197195
align-items: center;
198196
gap: 0.5rem;
@@ -203,25 +201,22 @@
203201
.navLink::after {
204202
content: '';
205203
position: absolute;
206-
bottom: 0.25rem;
207-
left: 50%;
204+
bottom: 0;
205+
left: 0;
208206
width: 0;
209-
height: 2px;
207+
height: 1px;
210208
background: var(--matrix-green, #00ff00);
211-
box-shadow: 0 0 8px rgba(0, 255, 0, 0.8);
212-
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
213-
transform: translateX(-50%);
209+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
214210
}
215211

216212
.navLink:hover,
217213
.navLink.active {
218-
color: var(--matrix-green, #00ff00);
219-
text-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
214+
color: #ffffff;
220215
}
221216

222217
.navLink:hover::after,
223218
.navLink.active::after {
224-
width: 85%;
219+
width: 100%;
225220
}
226221

227222
.navIcon {
@@ -244,18 +239,19 @@
244239
visibility: visible !important;
245240
flex-direction: row !important;
246241
padding: 0 !important;
247-
gap: 2rem !important;
242+
gap: 1.5rem !important;
248243
border: none !important;
249-
margin-top: 10px;
244+
margin: 0 !important;
245+
align-items: center;
250246
}
251247

252248
.menuToggle {
253249
display: none !important;
254250
}
255251

256252
.navLink {
257-
color: rgba(0, 255, 0, 0.8) !important;
258-
font-weight: 500 !important;
253+
color: rgba(255, 255, 255, 0.6) !important;
254+
font-weight: 400 !important;
259255
}
260256
}
261257

@@ -333,14 +329,6 @@
333329
.nav {
334330
align-items: center;
335331
}
336-
337-
/* Ensure theme toggle aligns perfectly with nav items */
338-
.nav > :last-child {
339-
margin-left: 0.5rem;
340-
align-self: center;
341-
display: flex;
342-
align-items: center;
343-
}
344332
}
345333

346334
/* Matrix rain effect - only on logo hover */
@@ -548,18 +536,18 @@
548536
}
549537

550538
[data-theme="dark"] .siteHeader {
551-
background: rgba(0, 0, 0, 0.95);
552-
border-bottom: 1px solid rgba(74, 158, 255, 0.5) !important; /* Blue border */
539+
background: #000000;
540+
border-bottom: 1px solid rgba(74, 158, 255, 0.2) !important;
553541
}
554542

555543
[data-theme="dark"] .siteHeader.scrolled {
556-
background: rgba(0, 0, 0, 0.98);
557-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
544+
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.5);
545+
border-bottom-color: rgba(74, 158, 255, 0.3) !important;
558546
}
559547

560548
[data-theme="dark"] .headerTitle h1 {
561-
color: #4A9EFF !important; /* Blue to match nav links */
562-
text-shadow: 0 0 10px rgba(74, 158, 255, 0.3);
549+
color: #4A9EFF !important;
550+
text-shadow: none;
563551
font-weight: 500;
564552
}
565553

@@ -577,18 +565,12 @@
577565
}
578566

579567
[data-theme="dark"] .navLink {
580-
color: #4A9EFF; /* Blue nav links */
581-
font-weight: 400;
582-
}
583-
584-
[data-theme="dark"] .navLink:hover {
585-
color: #5AADFF; /* Lighter blue on hover */
586-
text-shadow: 0 0 10px rgba(74, 158, 255, 0.3);
587-
background: none !important; /* Force remove background in dark mode */
568+
color: rgba(255, 255, 255, 0.6);
588569
}
589570

571+
[data-theme="dark"] .navLink:hover,
590572
[data-theme="dark"] .navLink.active {
591-
color: #5AADFF; /* Blue active state */
573+
color: #ffffff;
592574
}
593575

594576
[data-theme="dark"] .menuToggle span {
@@ -618,7 +600,5 @@
618600

619601
/* Hardware acceleration for smooth animations */
620602
.siteHeader {
621-
will-change: transform;
622603
transform: translateZ(0);
623-
-webkit-transform: translateZ(0);
624604
}

0 commit comments

Comments
 (0)