Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions public/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"pageTitles": {
"notFound": "Seite nicht gefunden | KamyCoding",
"legalNotice": "Impressum | KamyCoding",
"privacyPolicy": "Datenschutzerklärung | KamyCoding"
"privacyPolicy": "Datenschutzerklärung | KamyCoding",
"projectDetail": "Projekt | KamyCoding"
},
"nav": {
"about": "Über mich",
Expand Down Expand Up @@ -120,15 +121,15 @@
"profileAria": "LinkedIn-Profil von {{name}} ansehen",
"items": {
"tobiasLange": {
"quote": "Karl hat das Team mit seiner großartigen Organisation und klaren Kommunikation wirklich zusammengehalten. Ohne seinen Einsatz wären wir nicht so weit gekommen.",
"quote": "Kamyar hat das Team mit seiner großartigen Organisation und klaren Kommunikation wirklich zusammengehalten. Ohne seinen Einsatz wären wir nicht so weit gekommen.",
"role": "Frontend Developer"
},
"mariaSchaefer": {
"quote": "Die Zusammenarbeit mit Karl war eine große Freude. Er versteht es, Teammitglieder zu motivieren und zu ermutigen, ihre bestmögliche Arbeit zu zeigen, und bringt stets neue Impulse in das Brainstorming ein. Für das Wohlbefinden der Gruppe hatte er immer ein offenes Ohr, war hilfsbereit und brachte außerdem viel Humor mit.",
"quote": "Die Zusammenarbeit mit Kamyar war eine große Freude. Er versteht es, Teammitglieder zu motivieren und zu ermutigen, ihre bestmögliche Arbeit zu zeigen, und bringt stets neue Impulse in das Brainstorming ein. Für das Wohlbefinden der Gruppe hatte er immer ein offenes Ohr, war hilfsbereit und brachte außerdem viel Humor mit.",
"role": "Frontend Developer"
},
"davidBraun": {
"quote": "Karl war bei DA ein hervorragender Teamkollege. Sein positiver Einsatz und seine Bereitschaft, Verantwortung zu übernehmen, haben wesentlich dazu beigetragen, dass wir unsere Ziele erreicht haben.",
"quote": "Kamyar war bei DA ein hervorragender Teamkollege. Sein positiver Einsatz und seine Bereitschaft, Verantwortung zu übernehmen, haben wesentlich dazu beigetragen, dass wir unsere Ziele erreicht haben.",
"role": "Frontend Developer"
}
}
Expand Down
9 changes: 5 additions & 4 deletions public/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"pageTitles": {
"notFound": "Page Not Found | KamyCoding",
"legalNotice": "Legal Notice | KamyCoding",
"privacyPolicy": "Privacy Policy | KamyCoding"
"privacyPolicy": "Privacy Policy | KamyCoding",
"projectDetail": "Project | KamyCoding"
},
"nav": {
"about": "About me",
Expand Down Expand Up @@ -120,15 +121,15 @@
"profileAria": "View {{name}}'s LinkedIn profile",
"items": {
"tobiasLange": {
"quote": "Karl really kept the team together with his great organization and clear communication. We wouldn't have got this far without his commitment.",
"quote": "Kamyar really kept the team together with his great organization and clear communication. We wouldn't have got this far without his commitment.",
"role": "Frontend Developer"
},
"mariaSchaefer": {
"quote": "It was a great pleasure to work with Karl. He knows how to push and encourage team members to present the best work possible, always adding something to brainstorm. Regarding the well-being of group members, he was always present and available to listen and help others, with a great sense of humor as well.",
"quote": "It was a great pleasure to work with Kamyar. He knows how to push and encourage team members to present the best work possible, always adding something to brainstorm. Regarding the well-being of group members, he was always present and available to listen and help others, with a great sense of humor as well.",
"role": "Frontend Developer"
},
"davidBraun": {
"quote": "Karl was a top team colleague at DA. His positive commitment and willingness to take on responsibility made a significant contribution to us achieving our goals.",
"quote": "Kamyar was a top team colleague at DA. His positive commitment and willingness to take on responsibility made a significant contribution to us achieving our goals.",
"role": "Frontend Developer"
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const routes: Routes = [
path: 'projects/:slug',
component: ProjectDetail,
canActivate: [projectDetailGuard],
title: 'Project - Kamycoding',
data: { titleKey: 'pageTitles.projectDetail' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the project-specific title after language changes

When the user switches languages while viewing a project, LocalizedTitleStrategy reacts to this new key and sets the document title to the generic Project | KamyCoding/Projekt | KamyCoding. The component's title effect only depends on the project signal, so it does not rerun to restore Join | KamyCoding, causing every project page to lose its specific title after a language change.

Useful? React with 👍 / 👎.

},
{
path: '**',
Expand Down
30 changes: 14 additions & 16 deletions src/app/pages/home/sections/contact/contact.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,20 @@
}

.contact-field {
position: relative;
display: flex;
flex-direction: column;
gap: 10px;
display: grid;
gap: 8px;
padding: 16px 24px;
border-bottom: 1px solid var(--color-secondary);
}

.contact-field label {
display: block;
font-size: 24px;
font-weight: 500;
line-height: 1.2;
transition: color 180ms ease-out;
}

.contact-field input,
.contact-field textarea {
display: block;
.contact-field :is(input, textarea) {
width: 100%;
height: 22px;
margin: 0;
Expand Down Expand Up @@ -61,20 +56,23 @@
}

.contact-field__error {
position: absolute;
right: 24px;
bottom: 16px;
left: 24px;
margin: 0;
color: var(--color-error);
font-size: 14px;
line-height: 1.2;
pointer-events: none;
}

.contact-field--invalid input::placeholder,
.contact-field--invalid textarea::placeholder {
opacity: 0;
.contact-field--invalid:has(:placeholder-shown) :is(input, textarea) {
grid-area: 2 / 1;
z-index: 1;
}

.contact-field--invalid:has(:placeholder-shown) .contact-field__error {
grid-area: 2 / 1;
}

.contact-field--invalid:has(:placeholder-shown) ::placeholder {
color: transparent;
}
Comment on lines +74 to 76

.contact-consent {
Expand Down
25 changes: 22 additions & 3 deletions src/app/pages/home/sections/hero/hero.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
.hero {
position: relative;
min-height: 812px;
min-height: 100svh;
Comment on lines 7 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Size the desktop stage with the viewport-height hero

At desktop widths where the viewport is taller than the stage's 8 / 5 aspect-ratio height (for example, 1920×1080 or a 1024px-wide portrait tablet), this minimum expands .hero while .hero__stage remains capped by its width and 900px maximum. All stage-relative content—including the social navigation positioned from the stage bottom—therefore stays near the top, leaving a large empty strip before the next section instead of laying out across the new viewport-height hero.

Useful? React with 👍 / 👎.

overflow: hidden;
background: var(--color-foreground);
color: var(--color-foreground);
}

@supports (height: 100dvh) {
.hero {
min-height: 100dvh;
}
}

.hero__background {
position: absolute;
inset: 0;
Expand Down Expand Up @@ -165,11 +172,23 @@
outline-offset: 4px;
}

@media (min-width: 64rem) {
.hero {
min-height: 0;
@media (max-width: 63.9375rem) and (max-height: 700px) {
.hero__composition {
top: 112px;
gap: 22px;
}

.hero__polaroid {
width: 165px;
height: 198px;
}
Comment on lines +181 to +184

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fit the shortened polaroid around its children

On viewports at most 700px tall, this 198px border-box still contains 14px top padding, the newly configured 143px portrait, and the unchanged 54px caption, requiring 211px in total. Since the figure does not hide overflow, the caption extends 13px beyond the white polaroid background on the exact short-mobile layouts this media query targets.

Useful? React with 👍 / 👎.


.hero__portrait {
height: 143px;
}
}

@media (min-width: 64rem) {
.hero__stage {
container-type: inline-size;
width: min(100%, 1440px);
Expand Down
4 changes: 4 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
<head>
<meta charset="utf-8" />
<title>Kamyar Zamanfar | Full-Stack Developer</title>
<meta
name="description"
content="Portfolio of Kamyar Zamanfar (KamyCoding), a full-stack developer building modern, responsive web applications with a background in design."
/>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0e1013" />
Expand Down