Logo and responsiveness changes

This commit is contained in:
2025-05-28 01:07:13 -06:00
parent 0b02d6d5a0
commit b2426a6071
10 changed files with 489 additions and 435 deletions

View File

@ -13,23 +13,24 @@
"@astrojs/node": "^9.2.2", "@astrojs/node": "^9.2.2",
"@astrojs/preact": "^4.1.0", "@astrojs/preact": "^4.1.0",
"@astrojs/rss": "^4.0.11", "@astrojs/rss": "^4.0.11",
"@preact/signals": "^2.0.4", "@preact/signals": "^2.1.1",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "^4.1.7", "@tailwindcss/vite": "^4.1.7",
"astro": "^5.8.0", "astro": "^5.8.0",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"lucide-preact": "^0.511.0", "lucide-preact": "^0.511.0",
"preact": "^10.26.6", "preact": "^10.26.7",
"sharp": "^0.34.2", "sharp": "^0.34.2",
"tailwindcss": "^4.1.7" "tailwindcss": "^4.1.7"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@iconify-json/simple-icons": "^1.2.35", "@iconify-json/simple-icons": "^1.2.36",
"daisyui": "^5.0.37" "daisyui": "^5.0.38"
}, },
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"esbuild",
"sharp" "sharp"
] ]
} }

702
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 574 KiB

After

Width:  |  Height:  |  Size: 574 KiB

BIN
public/logo_real.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

View File

@ -44,49 +44,49 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
return ( return (
<div <div
class={`fixed bottom-4 left-1/2 transform -translate-x-1/2 z-20 transition-all duration-300 ${ class={`fixed bottom-3 sm:bottom-4 left-1/2 transform -translate-x-1/2 z-20 transition-all duration-300 ${
isScrolling.value ? "opacity-30" : "opacity-100" isScrolling.value ? "opacity-30" : "opacity-100"
} ${isVisible.value ? "translate-y-0" : "translate-y-20"}`} } ${isVisible.value ? "translate-y-0" : "translate-y-20"}`}
> >
<div class="overflow-visible"> <div class="overflow-visible">
<ul class="menu menu-horizontal bg-base-200 rounded-box p-2 shadow-lg flex flex-nowrap whitespace-nowrap"> <ul class="menu menu-horizontal bg-base-200 rounded-box p-1.5 sm:p-2 shadow-lg flex flex-nowrap whitespace-nowrap">
<li class="mx-1"> <li class="mx-0.5 sm:mx-1">
<a href="/" class={currentPath === "/" ? "menu-active" : ""}> <a href="/" class={currentPath === "/" ? "menu-active" : ""}>
<div class="tooltip" data-tip="Home"> <div class="tooltip" data-tip="Home">
<Home /> <Home size={18} class="sm:w-5 sm:h-5" />
</div> </div>
</a> </a>
</li> </li>
<li class="mx-1"> <li class="mx-0.5 sm:mx-1">
<a <a
href="/posts" href="/posts"
class={isPostsPath(currentPath) ? "menu-active" : ""} class={isPostsPath(currentPath) ? "menu-active" : ""}
> >
<div class="tooltip" data-tip="Posts"> <div class="tooltip" data-tip="Posts">
<NotebookPen /> <NotebookPen size={18} class="sm:w-5 sm:h-5" />
</div> </div>
</a> </a>
</li> </li>
<li class="mx-1"> <li class="mx-0.5 sm:mx-1">
<a <a
href="/resume" href="/resume"
class={currentPath === "/resume" ? "menu-active" : ""} class={currentPath === "/resume" ? "menu-active" : ""}
> >
<div class="tooltip" data-tip="Resume"> <div class="tooltip" data-tip="Resume">
<FileText /> <FileText size={18} class="sm:w-5 sm:h-5" />
</div> </div>
</a> </a>
</li> </li>
<li class="mx-1"> <li class="mx-0.5 sm:mx-1">
<a <a
href="/projects" href="/projects"
class={currentPath.startsWith("/projects") ? "menu-active" : ""} class={currentPath.startsWith("/projects") ? "menu-active" : ""}
> >
<div class="tooltip" data-tip="Projects"> <div class="tooltip" data-tip="Projects">
<CodeXml /> <CodeXml size={18} class="sm:w-5 sm:h-5" />
</div> </div>
</a> </a>
</li> </li>

View File

@ -66,21 +66,21 @@ export default function SkillsSection({ title, skills }: SkillsSectionProps) {
}; };
return ( return (
<div id="skills-section" class="card bg-base-200 shadow-xl mb-6"> <div id="skills-section" class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{title || "Skills"}</h2> <h2 class="card-title text-xl sm:text-2xl">{title || "Skills"}</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-3 sm:gap-4">
{skills.map((skill) => { {skills.map((skill) => {
const currentLevel = animatedLevels.value[skill.id] || 0; const currentLevel = animatedLevels.value[skill.id] || 0;
const progressValue = currentLevel * 20; // Convert 1-5 scale to 0-100 const progressValue = currentLevel * 20; // Convert 1-5 scale to 0-100
return ( return (
<div key={skill.id}> <div key={skill.id}>
<label class="label"> <label class="label p-1 sm:p-2">
<span class="label-text">{skill.name}</span> <span class="label-text text-sm sm:text-base">{skill.name}</span>
</label> </label>
<progress <progress
class="progress progress-primary w-full transition-all duration-100 ease-out" class="progress progress-primary w-full h-2 sm:h-3 transition-all duration-100 ease-out"
value={progressValue} value={progressValue}
max="100" max="100"
> >

View File

@ -17,7 +17,7 @@ import '../styles/global.css';
<ClientRouter /> <ClientRouter />
</head> </head>
<body class="flex flex-col min-h-screen"> <body class="flex flex-col min-h-screen">
<main class="flex-grow flex flex-col gap-4 items-center justify-center"> <main class="flex-grow flex flex-col gap-4 items-center justify-center pb-24 sm:pb-20">
<slot /> <slot />
</main> </main>
<NavigationBar client:load currentPath={currentPath} /> <NavigationBar client:load currentPath={currentPath} />

View File

@ -7,7 +7,7 @@ import Layout from "../layouts/Layout.astro";
<Layout> <Layout>
<Image <Image
src="/logo.webp" src="/logo_real.webp"
alt="A drawing of Atridad Lahiji by Shelze!" alt="A drawing of Atridad Lahiji by Shelze!"
height={150} height={150}
width={150} width={150}
@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
Atridad Lahiji Atridad Lahiji
</h1> </h1>
<h2 class="text-xl sm:text-3xl font-bol text-center"> <h2 class="text-xl sm:text-3xl font-bold text-center">
Researcher, Full-Stack Developer, and IT Professional. Researcher, Full-Stack Developer, and IT Professional.
</h2> </h2>

View File

@ -56,7 +56,7 @@ const data = resumeData;
{(!data || fetchError) && ( {(!data || fetchError) && (
<Layout> <Layout>
<div class="container mx-auto p-4 max-w-4xl text-center"> <div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl text-center w-full">
<h1 class="text-2xl font-bold text-red-600">Error loading resume data.</h1> <h1 class="text-2xl font-bold text-red-600">Error loading resume data.</h1>
<p>{fetchError || "Please try refreshing the page."}</p> <p>{fetchError || "Please try refreshing the page."}</p>
</div> </div>
@ -65,51 +65,51 @@ const data = resumeData;
{data && !fetchError && ( {data && !fetchError && (
<Layout> <Layout>
<div class="container mx-auto p-4 max-w-4xl"> <div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl w-full">
<h1 class="text-4xl font-bold mb-6 text-center">{data.basics.name}</h1> <h1 class="text-3xl sm:text-4xl font-bold mb-4 sm:mb-6 text-center">{data.basics.name}</h1>
<div class="flex justify-center items-center flex-wrap gap-x-4 gap-y-2 mb-6"> <div class="flex justify-center items-center flex-wrap gap-x-3 sm:gap-x-4 gap-y-2 mb-4 sm:mb-6">
{data.basics.email && ( {data.basics.email && (
<a href={`mailto:${data.basics.email}`} class="link link-hover inline-flex items-center gap-1"> <a href={`mailto:${data.basics.email}`} class="link link-hover inline-flex items-center gap-1 text-sm sm:text-base">
<Icon name="mdi:email" /> {data.basics.email} <Icon name="mdi:email" /> {data.basics.email}
</a> </a>
)} )}
{data.sections.profiles.items.find(p => p.network === "GitHub") && ( {data.sections.profiles.items.find(p => p.network === "GitHub") && (
<a href={data.sections.profiles.items.find(p => p.network === "GitHub")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1"> <a href={data.sections.profiles.items.find(p => p.network === "GitHub")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1 text-sm sm:text-base">
<Icon name="simple-icons:github" /> GitHub <Icon name="simple-icons:github" /> GitHub
</a> </a>
)} )}
{data.sections.profiles.items.find(p => p.network === "linkedin") && ( {data.sections.profiles.items.find(p => p.network === "linkedin") && (
<a href={data.sections.profiles.items.find(p => p.network === "linkedin")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1"> <a href={data.sections.profiles.items.find(p => p.network === "linkedin")!.url.href} target="_blank" rel="noopener noreferrer" class="link link-hover inline-flex items-center gap-1 text-sm sm:text-base">
<Icon name="simple-icons:linkedin" /> LinkedIn <Icon name="simple-icons:linkedin" /> LinkedIn
</a> </a>
)} )}
</div> </div>
<div class="text-center mb-8"> <div class="text-center mb-6 sm:mb-8">
<a <a
href="/files/Atridad_Lahiji_Resume.pdf" href="/files/Atridad_Lahiji_Resume.pdf"
download="Atridad_Lahiji_Resume.pdf" download="Atridad_Lahiji_Resume.pdf"
class="btn btn-primary inline-flex items-center gap-2" class="btn btn-primary inline-flex items-center gap-2 text-sm sm:text-base"
> >
<Icon name="mdi:download" /> Download Resume (PDF) <Icon name="mdi:download" /> Download Resume (PDF)
</a> </a>
</div> </div>
{data.sections.summary && ( {data.sections.summary && (
<div class="card bg-base-200 shadow-xl mb-6"> <div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{data.sections.summary.name || "Summary"}</h2> <h2 class="card-title text-xl sm:text-2xl">{data.sections.summary.name || "Summary"}</h2>
<div set:html={data.sections.summary.content}></div> <div set:html={data.sections.summary.content}></div>
</div> </div>
</div> </div>
)} )}
{data.sections.profiles && data.sections.profiles.items && data.sections.profiles.items.length > 0 && ( {data.sections.profiles && data.sections.profiles.items && data.sections.profiles.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6"> <div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{data.sections.profiles.name || "Profiles"}</h2> <h2 class="card-title text-xl sm:text-2xl">{data.sections.profiles.name || "Profiles"}</h2>
<div class="flex flex-wrap gap-4"> <div class="flex flex-wrap gap-3 sm:gap-4">
{data.sections.profiles.items.map((profile) => { {data.sections.profiles.items.map((profile) => {
let iconName = "mdi:web"; let iconName = "mdi:web";
const networkLower = profile.network.toLowerCase(); const networkLower = profile.network.toLowerCase();
@ -122,7 +122,7 @@ const data = resumeData;
href={profile.url.href} href={profile.url.href}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="link link-hover inline-flex items-center gap-1" class="link link-hover inline-flex items-center gap-1 text-sm sm:text-base"
> >
<Icon name={iconName} /> {profile.network} ({profile.username}) <Icon name={iconName} /> {profile.network} ({profile.username})
</a> </a>
@ -142,29 +142,34 @@ const data = resumeData;
)} )}
{data.sections.experience && data.sections.experience.items && data.sections.experience.items.length > 0 && ( {data.sections.experience && data.sections.experience.items && data.sections.experience.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6"> <div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{data.sections.experience.name || "Experience"}</h2> <h2 class="card-title text-xl sm:text-2xl">{data.sections.experience.name || "Experience"}</h2>
<div class="space-y-4"> <div class="space-y-3 sm:space-y-4">
{data.sections.experience.items.map((exp, index) => ( {data.sections.experience.items.map((exp, index) => (
<details class="collapse collapse-arrow bg-base-100" open={index === 0 ? true : undefined}> <details class="collapse collapse-arrow bg-base-100" open={index === 0 ? true : undefined}>
<summary class="collapse-title text-xl font-medium"> <summary class="collapse-title text-lg sm:text-xl font-medium p-3 sm:p-4">
{exp.position} at {exp.company} ({exp.date}) <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-1 sm:gap-2">
<span class="font-semibold">{exp.position} at {exp.company}</span>
<div class="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3 text-sm sm:text-base font-normal">
<span>{exp.date}</span>
{exp.location && ( {exp.location && (
<span class="text-sm font-normal float-right pt-1">{exp.location}</span> <span class="text-base-content/70">{exp.location}</span>
)} )}
</div>
</div>
</summary> </summary>
<div class="collapse-content"> <div class="collapse-content p-3 sm:p-4">
{exp.url && exp.url.href && ( {exp.url && exp.url.href && (
<a href={exp.url.href} target="_blank" rel="noopener noreferrer" class="link link-primary block mb-2">{exp.url.href}</a> <a href={exp.url.href} target="_blank" rel="noopener noreferrer" class="link link-primary block mb-2 text-sm sm:text-base break-all">{exp.url.href}</a>
)} )}
<div class="mt-2"> <div class="mt-2">
<ul class="list"> <ul class="list space-y-1">
{exp.summary.replace(/<\/?ul>|<\/?p>/g, '') {exp.summary.replace(/<\/?ul>|<\/?p>/g, '')
.split('<li>') .split('<li>')
.filter(item => item.trim() !== '') .filter(item => item.trim() !== '')
.map(item => ( .map(item => (
<li class="list-row"> <li class="list-row text-sm sm:text-base">
{item.replace('</li>', '')} {item.replace('</li>', '')}
</li> </li>
)) ))
@ -180,16 +185,16 @@ const data = resumeData;
)} )}
{data.sections.education && data.sections.education.items && data.sections.education.items.length > 0 && ( {data.sections.education && data.sections.education.items && data.sections.education.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6"> <div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{data.sections.education.name || "Education"}</h2> <h2 class="card-title text-xl sm:text-2xl">{data.sections.education.name || "Education"}</h2>
<div class="space-y-4"> <div class="space-y-3 sm:space-y-4">
{data.sections.education.items.map((edu, index) => ( {data.sections.education.items.map((edu, index) => (
<div> <div>
<h3 class="text-lg font-semibold">{edu.institution}</h3> <h3 class="text-base sm:text-lg font-semibold">{edu.institution}</h3>
<p>{edu.studyType} - {edu.area} ({edu.date})</p> <p class="text-sm sm:text-base">{edu.studyType} - {edu.area} ({edu.date})</p>
{edu.summary && ( {edu.summary && (
<div class="ml-4 text-sm mt-1" set:html={edu.summary}></div> <div class="ml-2 sm:ml-4 text-xs sm:text-sm mt-1" set:html={edu.summary}></div>
)} )}
</div> </div>
))} ))}
@ -199,14 +204,14 @@ const data = resumeData;
)} )}
{data.sections.volunteer && data.sections.volunteer.items && data.sections.volunteer.items.length > 0 && ( {data.sections.volunteer && data.sections.volunteer.items && data.sections.volunteer.items.length > 0 && (
<div class="card bg-base-200 shadow-xl mb-6"> <div class="card bg-base-200 shadow-xl mb-4 sm:mb-6">
<div class="card-body"> <div class="card-body p-4 sm:p-6">
<h2 class="card-title text-2xl">{data.sections.volunteer.name || "Volunteering"}</h2> <h2 class="card-title text-xl sm:text-2xl">{data.sections.volunteer.name || "Volunteering"}</h2>
<div class="space-y-4"> <div class="space-y-3 sm:space-y-4">
{data.sections.volunteer.items.map((vol, index) => ( {data.sections.volunteer.items.map((vol, index) => (
<div> <div>
<h3 class="text-lg font-semibold">{vol.organization}</h3> <h3 class="text-base sm:text-lg font-semibold">{vol.organization}</h3>
<p>{vol.position} ({vol.date})</p> <p class="text-sm sm:text-base">{vol.position} ({vol.date})</p>
</div> </div>
))} ))}
</div> </div>

View File

@ -35,3 +35,51 @@
--depth: 1; --depth: 1;
--noise: 1; --noise: 1;
} }
/* Ensure better text scaling and overflow handling */
* {
/* Allow text to scale with user preferences */
text-size-adjust: 100%;
}
/* Prevent horizontal overflow on smaller screens or when zoomed */
body {
overflow-x: hidden;
}
/* Ensure links and buttons remain accessible at all zoom levels */
a, button {
min-height: 44px;
min-width: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Make sure card content doesn't overflow */
.card-body {
overflow-wrap: break-word;
word-break: break-word;
}
/* Ensure progress bars scale properly */
.progress {
min-height: 0.5rem;
}
/* Responsive navigation improvements */
@media (max-width: 640px) {
.menu-horizontal .menu li {
margin: 0 0.125rem;
}
}
/* Better tooltip positioning for mobile */
@media (max-width: 768px) {
.tooltip:before,
.tooltip:after {
transform: translateX(-50%) translateY(-100%);
top: auto;
bottom: 100%;
}
}