Conversation
There was a problem hiding this comment.
Pull request overview
This PR merges the gh branch into main and substantially restructures the portfolio SPA: it replaces the prior React Router + MUI dashboard-based layout with a Tailwind-driven CV-centric layout, adds several interactive “demo” dialogs, and introduces a GitHub Pages deployment workflow.
Changes:
- Switch app structure from router-driven MUI dashboard pages to a single-page CV layout backed by static data (
src/data/cv-data.ts). - Add Tailwind CSS 4 integration via
@tailwindcss/vite, update global styles + fonts, and adjust build/tooling configuration. - Add new pages/components/demos (CV page shell, skills/publications/experience cards, hobby masonry wall, interactive demo dialogs).
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
vite.config.ts |
Adds Tailwind Vite plugin and React/ReactDOM dedupe. |
tsconfig.app.json |
Updates TS compiler options and path alias mapping. |
src/widgets/layout/NavigationDrawer.tsx |
Removes old MUI navigation drawer. |
src/widgets/layout/Footer.tsx |
Removes old MUI footer component. |
src/widgets/layout/AppBarNav.tsx |
Removes old MUI app bar/navigation component. |
src/widgets/cards/ProfileInfoCard.tsx |
Removes old MUI profile info card widget. |
src/theme.ts |
Removes MUI theme definition. |
src/routes.tsx |
Removes React Router route configuration. |
src/pages/Projects.tsx |
Removes old Projects page (MUI-based). |
src/pages/HobbiesPage.tsx |
Adds Tailwind-based masonry hobbies page with lightbox + infinite scroll. |
src/pages/Experience.tsx |
Removes old resume PDF viewer page (react-pdf). |
src/pages/CVPage.tsx |
Adds new CV page shell with sticky section nav, dialogs, and section layout. |
src/pages/Blog.tsx |
Removes old Blog placeholder page (MUI-based). |
src/pages/AboutMePage.tsx |
Adds Tailwind “About Me” page variant with link highlight card(s). |
src/pages/AboutMe.tsx |
Removes old MUI About Me page. |
src/main.tsx |
Simplifies app bootstrap (removes router/theme/context wrappers). |
src/layouts/Dashboard.tsx |
Removes router-based dashboard layout. |
src/global.css |
Adds Tailwind import + theme font variables; keeps base box-sizing/height rules. |
src/demos/TerminalDemo.tsx |
Adds interactive terminal-style skills explorer demo. |
src/demos/SpreadsheetDemo.tsx |
Adds spreadsheet + canvas latency chart demo. |
src/demos/SkillDemoDispatcher.tsx |
Adds dispatcher mapping skill categories to demo dialogs. |
src/demos/RequestFlowDemo.tsx |
Adds request flow visualization demo. |
src/demos/PipelineDemo.tsx |
Adds CI/CD pipeline simulation demo. |
src/demos/InfraTopologyDemo.tsx |
Adds draggable infrastructure topology demo. |
src/demos/DialogShell.tsx |
Adds reusable modal/dialog shell for demos. |
src/demos/ComponentTreeDemo.tsx |
Adds component tree visualization demo. |
src/demos/AlignmentDemo.tsx |
Adds alignment visualization demo. |
src/data/cv-data.ts |
Introduces centralized CV content + theme tokens + section config. |
src/context/index.tsx |
Removes old app context (drawer state). |
src/components/SkillsSection.tsx |
Adds skills section cards that open demos. |
src/components/shared.tsx |
Adds shared useInView, Tag, and SectionLabel utilities. |
src/components/PublicationCard.tsx |
Adds publication card + publication dialog. |
src/components/ExperienceCard.tsx |
Adds experience timeline card. |
src/components/EducationCard.tsx |
Adds education card section. |
src/App.tsx |
Replaces router-based app with single-page CV layout + minimal header/footer. |
package.json |
Updates dependencies/devDependencies for Tailwind Vite plugin and other package changes. |
package-lock.json |
Locks updated dependency graph (Tailwind/MUI/etc). |
index.html |
Updates Google Fonts import to Playfair Display / DM Sans / Fira Code. |
CLAUDE.md |
Adds repository guidance document for Claude Code. |
.github/workflows/deploy.yml |
Adds GitHub Pages deployment workflow (build + deploy dist/). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /* Path aliases */ | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@/*": ["src/*"] | ||
| "@/*": ["./src/*"] | ||
| }, |
There was a problem hiding this comment.
compilerOptions.paths is configured but baseUrl was removed. TypeScript requires baseUrl when using paths (otherwise compilation fails with an option error). Re-add "baseUrl": "." (or another appropriate base) or remove paths and rely solely on Vite aliases.
| <button | ||
| onClick={onClick} | ||
| className={`group relative block w-full overflow-hidden rounded-2xl bg-gray-100 cursor-zoom-in | ||
| ${ASPECT_RATIO[item.aspectHint]} | ||
| transition-transform duration-300 ease-out hover:scale-[1.025] | ||
| shadow-sm hover:shadow-xl hover:shadow-black/10`} | ||
| > | ||
| <img | ||
| src={item.src} | ||
| alt="" | ||
| loading="lazy" | ||
| decoding="async" | ||
| className="absolute inset-0 w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" | ||
| /> | ||
| <div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors duration-300 rounded-2xl" /> | ||
| </button> |
There was a problem hiding this comment.
These media cards are interactive (<button> opens the lightbox) but the contained images use empty alt text and the button has no accessible name. This makes the grid difficult to use with screen readers. Consider providing an aria-label on the button and/or meaningful alt text (e.g., from caption/location/date when present).
| <button | ||
| onClick={(e) => { e.stopPropagation(); prev(); }} | ||
| className="fixed left-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white flex items-center justify-center transition-colors" | ||
| > | ||
| ‹ | ||
| </button> | ||
| <button | ||
| onClick={(e) => { e.stopPropagation(); next(); }} | ||
| className="fixed right-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white flex items-center justify-center transition-colors" | ||
| > | ||
| › | ||
| </button> | ||
| </> | ||
| )} | ||
|
|
||
| <button | ||
| onClick={handleClose} | ||
| className="fixed top-4 right-4 w-9 h-9 rounded-full bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white flex items-center justify-center text-lg transition-colors" | ||
| > | ||
| × | ||
| </button> | ||
|
|
||
| <div className="fixed bottom-4 left-1/2 -translate-x-1/2 flex gap-1.5"> | ||
| {items.map((_, i) => ( | ||
| <button | ||
| key={i} | ||
| onClick={(e) => { e.stopPropagation(); setIdx(i); }} | ||
| className={`rounded-full transition-all duration-200 ${ | ||
| i === idx ? "w-5 h-1.5 bg-white" : "w-1.5 h-1.5 bg-white/40" | ||
| }`} | ||
| /> |
There was a problem hiding this comment.
Lightbox controls (prev/next/close and the pagination dots) don’t have aria-labels, so assistive technologies will announce them poorly (or not at all). Add descriptive labels (e.g., "Previous", "Next", "Close", "Go to item N") and consider setting type="button" on these buttons as well.
| if (!dragRef.current || !containerRef.current) return; | ||
| const rect = containerRef.current.getBoundingClientRect(); | ||
| const x = Math.max(0, Math.min(rect.width - NODE_W, e.clientX - rect.left - dragRef.current.offsetX)); | ||
| const y = Math.max(0, Math.min(360 - NODE_H, e.clientY - rect.top - dragRef.current.offsetY)); |
There was a problem hiding this comment.
Drag bounds clamp y using a hard-coded 360 height (Math.min(360 - NODE_H, ...)). This will break if the container height changes (or if it’s ever made responsive). Use rect.height (similar to rect.width) to compute the vertical clamp instead of a magic number.
| const y = Math.max(0, Math.min(360 - NODE_H, e.clientY - rect.top - dragRef.current.offsetY)); | |
| const y = Math.max(0, Math.min(rect.height - NODE_H, e.clientY - rect.top - dragRef.current.offsetY)); |
| transform: visible ? "translateX(0)" : "translateX(-14px)", | ||
| transition: `opacity 0.6s cubic-bezier(0.16,1,0.3,1) ${index * 0.1}s, | ||
| transform 0.6s cubic-bezier(0.16,1,0.3,1) ${index * 0.1}s, | ||
| border-color 0.2s, translate 0.2s`, |
There was a problem hiding this comment.
The inline transition string includes translate 0.2s, but this component animates via transform (including Tailwind’s hover:translate-x-1). translate is not the property being updated here and may be ignored, making the transition declaration misleading. Prefer transform 0.2s (or drop this part since transform is already included above).
| border-color 0.2s, translate 0.2s`, | |
| border-color 0.2s`, |
| * AboutMePage.tsx | ||
| * | ||
| * Drop-in replacement for the AboutMe section in App.tsx. | ||
| * - Removed "Outside Work" bio section |
There was a problem hiding this comment.
The file header comment says the "Outside Work" bio section was removed, but the component still renders an "Extracurriculars" section below. Please update the comment to reflect the current behavior so it doesn’t become misleading documentation.
| * - Removed "Outside Work" bio section | |
| * - Renamed the former "Outside Work" bio section to "Extracurriculars" |
No description provided.