From 98dedb0b2248e4601f478223ece9213406129d79 Mon Sep 17 00:00:00 2001 From: AdamBtech <60339324+AdamBtech@users.noreply.github.com> Date: Wed, 28 May 2025 14:25:19 +0200 Subject: [PATCH] Refactoring contact page in smaller components --- .../contact-content.component.css | 89 ----------- .../contact-content.component.html | 125 ++++++---------- .../contact-content.component.ts | 10 +- .../info-panel/info-panel.component.css | 84 +++++++++++ .../info-panel/info-panel.component.html | 11 ++ .../info-panel/info-panel.component.ts | 12 ++ .../link-card/link-card.component.css | 141 ++++++++++++++++++ .../link-card/link-card.component.html | 15 ++ .../link-card/link-card.component.ts | 13 ++ 9 files changed, 323 insertions(+), 177 deletions(-) create mode 100644 src/app/pages/contact/contact-content/info-panel/info-panel.component.css create mode 100644 src/app/pages/contact/contact-content/info-panel/info-panel.component.html create mode 100644 src/app/pages/contact/contact-content/info-panel/info-panel.component.ts create mode 100644 src/app/pages/contact/contact-content/link-card/link-card.component.css create mode 100644 src/app/pages/contact/contact-content/link-card/link-card.component.html create mode 100644 src/app/pages/contact/contact-content/link-card/link-card.component.ts diff --git a/src/app/pages/contact/contact-content/contact-content.component.css b/src/app/pages/contact/contact-content/contact-content.component.css index 86c5833..eb9c81d 100644 --- a/src/app/pages/contact/contact-content/contact-content.component.css +++ b/src/app/pages/contact/contact-content/contact-content.component.css @@ -39,12 +39,6 @@ to { opacity: 1; } } -@keyframes scanLine { - from { transform: translate3d(-100%, 0, 0); opacity: 0; } - 50% { opacity: 1; } - to { transform: translate3d(100%, 0, 0); opacity: 0; } -} - /* ===================== CONTACT ELEMENTS ===================== */ /* Content container */ @@ -71,59 +65,6 @@ animation: slideInUp 0.8s ease-out 0.8s forwards; } -/* Contact items */ -.contact-item { - opacity: 0; - animation: scaleIn 0.8s ease-out forwards; - position: relative; -} - -.contact-item:nth-child(1) { animation-delay: 1.0s; } -.contact-item:nth-child(2) { animation-delay: 1.1s; } -.contact-item:nth-child(3) { animation-delay: 1.2s; } - -/* Scan line effect */ -.contact-item::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 2px; - background: linear-gradient(90deg, transparent, var(--color-nier-accent), transparent); - animation: scanLine 1.5s ease-out forwards; - z-index: 20; -} - -.contact-item:nth-child(1)::before { animation-delay: 1.2s; } -.contact-item:nth-child(2)::before { animation-delay: 1.3s; } -.contact-item:nth-child(3)::before { animation-delay: 1.4s; } - -/* Contact icons */ -.contact-icon { - opacity: 0; - animation: scaleIn 0.5s ease-out forwards; -} - -.contact-item:nth-child(1) .contact-icon { animation-delay: 1.3s; } -.contact-item:nth-child(2) .contact-icon { animation-delay: 1.4s; } -.contact-item:nth-child(3) .contact-icon { animation-delay: 1.5s; } - -/* Contact labels and values */ -.contact-label, -.contact-value { - opacity: 0; - animation: slideInLeft 0.4s ease-out forwards; -} - -.contact-item:nth-child(1) .contact-label { animation-delay: 1.4s; } -.contact-item:nth-child(2) .contact-label { animation-delay: 1.5s; } -.contact-item:nth-child(3) .contact-label { animation-delay: 1.6s; } - -.contact-item:nth-child(1) .contact-value { animation-delay: 1.5s; } -.contact-item:nth-child(2) .contact-value { animation-delay: 1.6s; } -.contact-item:nth-child(3) .contact-value { animation-delay: 1.7s; } - /* Info panels container */ .info-panels-container { opacity: 0; @@ -156,22 +97,6 @@ .info-panel:nth-child(1) .info-panel-content { animation-delay: 1.9s; } .info-panel:nth-child(2) .info-panel-content { animation-delay: 2.0s; } -/* ===================== HOVER EFFECTS ===================== */ - -.contact-item:hover { - transform: translateY(-3px); - box-shadow: - 0 8px 25px rgba(0, 0, 0, 0.2), - 0 0 20px rgba(90, 90, 80, 0.1); - transition: all 0.3s ease; -} - -.contact-item:hover .contact-icon { - transform: scale(1.05); - box-shadow: 0 0 15px rgba(90, 90, 80, 0.3); - transition: all 0.3s ease; -} - /* ===================== BACKGROUND PATTERN ===================== */ .contact-content-container::before { @@ -196,11 +121,6 @@ .contact-content-container { animation-delay: 0.3s; } .availability-status { animation-delay: 0.4s; } .contact-grid { animation-delay: 0.6s; } - - .contact-item:nth-child(1) { animation-delay: 0.8s; } - .contact-item:nth-child(2) { animation-delay: 0.9s; } - \contact-item:nth-child(3) { animation-delay: 1.0s; } - .info-panels-container { animation-delay: 1.2s; } .info-panel:nth-child(1) { animation-delay: 1.3s; } .info-panel:nth-child(2) { animation-delay: 1.4s; } @@ -209,16 +129,12 @@ .contact-content-container, .availability-status, .contact-grid, - .contact-item, .info-panels-container, .info-panel { animation-duration: 0.6s; } .status-dot, - .contact-icon, - .contact-label, - .contact-value, .info-panel-title, .info-panel-content { animation-duration: 0.3s; @@ -237,12 +153,7 @@ transform: none !important; } - .contact-item::before, .contact-content-container::before { display: none !important; } - - .contact-item:hover { - transform: none; - } } diff --git a/src/app/pages/contact/contact-content/contact-content.component.html b/src/app/pages/contact/contact-content/contact-content.component.html index 92fd01c..0e70399 100644 --- a/src/app/pages/contact/contact-content/contact-content.component.html +++ b/src/app/pages/contact/contact-content/contact-content.component.html @@ -1,97 +1,56 @@
-
-
+
+
AVAILABLE FOR OPPORTUNITIES
-
- - -
- -
-
-
- PRIMARY COMMUNICATION CHANNEL -
-
- Email Access Granted
- Secure encrypted transmission protocol enabled -
-
-
- - - -
- -
-
-
- PROFESSIONAL NETWORK ACCESS -
-
- LinkedIn professional interface
- Connect for career opportunities and networking -
-
-
- - - -
- -
-
-
- SOURCE CODE REPOSITORY -
-
- GitHub development archives
- Access project source files and contribution history -
-
-
+
+ + +
-
+
-
-
- RESPONSE PROTOCOL -
-
- Standard response time: 24-48 hour cycle
- Emergency contact: Email protocol recommended
- Priority inquiries: LinkedIn messaging for urgent requests -
-
+ - -
-
- COLLABORATION STATUS -
-
- Currently seeking: Full-time opportunities, internships, freelance projects
- Specialization: Web development, Angular, modern tech stack
- Location: Remote-ready, French hideout base of operations -
-
+
diff --git a/src/app/pages/contact/contact-content/contact-content.component.ts b/src/app/pages/contact/contact-content/contact-content.component.ts index 42c0299..f2bea46 100644 --- a/src/app/pages/contact/contact-content/contact-content.component.ts +++ b/src/app/pages/contact/contact-content/contact-content.component.ts @@ -1,11 +1,11 @@ import { Component } from '@angular/core'; +import { InfoPanelComponent } from './info-panel/info-panel.component'; +import { LinkCardComponent } from './link-card/link-card.component'; @Component({ selector: 'app-contact-content', - imports: [], + imports: [InfoPanelComponent, LinkCardComponent], templateUrl: './contact-content.component.html', - styleUrl: './contact-content.component.css' + styleUrl: './contact-content.component.css', }) -export class ContactContentComponent { - -} +export class ContactContentComponent {} diff --git a/src/app/pages/contact/contact-content/info-panel/info-panel.component.css b/src/app/pages/contact/contact-content/info-panel/info-panel.component.css new file mode 100644 index 0000000..850e6ed --- /dev/null +++ b/src/app/pages/contact/contact-content/info-panel/info-panel.component.css @@ -0,0 +1,84 @@ +/* ===================== CONTACT PAGE ANIMATIONS ===================== */ + +/* Core keyframes - reused across components */ +@keyframes slideInLeft { + from { + opacity: 0; + transform: translate3d(-30px, 0, 0); + } + to { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +/* ===================== INFO PANELS ===================== */ + +/* Info panels */ +.info-panel { + opacity: 0; + animation: scaleIn 0.6s ease-out forwards; +} + +.info-panel:nth-child(1) { animation-delay: 1.6s; } +.info-panel:nth-child(2) { animation-delay: 1.7s; } + +/* Info panel titles and content */ +.info-panel-title { + opacity: 0; + animation: slideInLeft 0.4s ease-out forwards; +} + +.info-panel-content { + opacity: 0; + animation: fadeIn 0.4s ease-out forwards; +} + +.info-panel:nth-child(1) .info-panel-title { animation-delay: 1.8s; } +.info-panel:nth-child(2) .info-panel-title { animation-delay: 1.9s; } + +.info-panel:nth-child(1) .info-panel-content { animation-delay: 1.9s; } +.info-panel:nth-child(2) .info-panel-content { animation-delay: 2.0s; } + +/* ===================== RESPONSIVE DESIGN ===================== */ + +@media (max-width: 768px) { + .info-panel:nth-child(1) { animation-delay: 1.3s; } + .info-panel:nth-child(2) { animation-delay: 1.4s; } + + /* Faster animations on mobile */ + .info-panel { + animation-duration: 0.6s; + } + + .info-panel-title, + .info-panel-content { + animation-duration: 0.3s; + } +} + +/* ===================== ACCESSIBILITY ===================== */ + +@media (prefers-reduced-motion: reduce) { + *[class*="info-"] { + animation: none !important; + opacity: 1 !important; + transform: none !important; + } +} diff --git a/src/app/pages/contact/contact-content/info-panel/info-panel.component.html b/src/app/pages/contact/contact-content/info-panel/info-panel.component.html new file mode 100644 index 0000000..ea3ff80 --- /dev/null +++ b/src/app/pages/contact/contact-content/info-panel/info-panel.component.html @@ -0,0 +1,11 @@ +
+
+ {{ title() }} +
+
+
diff --git a/src/app/pages/contact/contact-content/info-panel/info-panel.component.ts b/src/app/pages/contact/contact-content/info-panel/info-panel.component.ts new file mode 100644 index 0000000..b86ecd7 --- /dev/null +++ b/src/app/pages/contact/contact-content/info-panel/info-panel.component.ts @@ -0,0 +1,12 @@ +import { Component, input } from '@angular/core'; + +@Component({ + selector: 'app-info-panel', + imports: [], + templateUrl: './info-panel.component.html', + styleUrl: './info-panel.component.css', +}) +export class InfoPanelComponent { + title = input.required(); + description = input.required(); +} diff --git a/src/app/pages/contact/contact-content/link-card/link-card.component.css b/src/app/pages/contact/contact-content/link-card/link-card.component.css new file mode 100644 index 0000000..a35aab2 --- /dev/null +++ b/src/app/pages/contact/contact-content/link-card/link-card.component.css @@ -0,0 +1,141 @@ +/* ===================== CONTACT PAGE ANIMATIONS ===================== */ + +/* Core keyframes - reused across components */ +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes scanLine { + from { transform: translate3d(-100%, 0, 0); opacity: 0; } + 50% { opacity: 1; } + to { transform: translate3d(100%, 0, 0); opacity: 0; } +} + +/* ===================== CONTACT ELEMENTS ===================== */ + +/* Contact items */ +.contact-item { + opacity: 0; + animation: scaleIn 0.8s ease-out forwards; + position: relative; +} + +.contact-item:nth-child(1) { animation-delay: 1.0s; } +.contact-item:nth-child(2) { animation-delay: 1.1s; } +.contact-item:nth-child(3) { animation-delay: 1.2s; } + +/* Scan line effect */ +.contact-item::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 2px; + background: linear-gradient(90deg, transparent, var(--color-nier-accent), transparent); + animation: scanLine 1.5s ease-out forwards; + z-index: 20; +} + +.contact-item:nth-child(1)::before { animation-delay: 1.2s; } +.contact-item:nth-child(2)::before { animation-delay: 1.3s; } +.contact-item:nth-child(3)::before { animation-delay: 1.4s; } + +/* Contact icons */ +.contact-icon { + opacity: 0; + animation: scaleIn 0.5s ease-out forwards; +} + +.contact-item:nth-child(1) .contact-icon { animation-delay: 1.3s; } +.contact-item:nth-child(2) .contact-icon { animation-delay: 1.4s; } +.contact-item:nth-child(3) .contact-icon { animation-delay: 1.5s; } + +/* Contact labels and values */ +.contact-label, +.contact-value { + opacity: 0; + animation: slideInLeft 0.4s ease-out forwards; +} + +@keyframes slideInLeft { + from { + opacity: 0; + transform: translate3d(-30px, 0, 0); + } + to { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +.contact-item:nth-child(1) .contact-label { animation-delay: 1.4s; } +.contact-item:nth-child(2) .contact-label { animation-delay: 1.5s; } +.contact-item:nth-child(3) .contact-label { animation-delay: 1.6s; } + +.contact-item:nth-child(1) .contact-value { animation-delay: 1.5s; } +.contact-item:nth-child(2) .contact-value { animation-delay: 1.6s; } +.contact-item:nth-child(3) .contact-value { animation-delay: 1.7s; } + +/* ===================== HOVER EFFECTS ===================== */ + +.contact-item:hover { + transform: translateY(-3px); + box-shadow: + 0 8px 25px rgba(0, 0, 0, 0.2), + 0 0 20px rgba(90, 90, 80, 0.1); + transition: all 0.3s ease; +} + +.contact-item:hover .contact-icon { + transform: scale(1.05); + box-shadow: 0 0 15px rgba(90, 90, 80, 0.3); + transition: all 0.3s ease; +} + +/* ===================== RESPONSIVE DESIGN ===================== */ + +@media (max-width: 768px) { + .contact-item:nth-child(1) { animation-delay: 0.8s; } + .contact-item:nth-child(2) { animation-delay: 0.9s; } + .contact-item:nth-child(3) { animation-delay: 1.0s; } + + /* Faster animations on mobile */ + .contact-item { + animation-duration: 0.6s; + } + + .contact-icon, + .contact-label, + .contact-value { + animation-duration: 0.3s; + } +} + +/* ===================== ACCESSIBILITY ===================== */ + +@media (prefers-reduced-motion: reduce) { + .contact-item, + .contact-icon, + .contact-label, + .contact-value { + animation: none !important; + opacity: 1 !important; + transform: none !important; + } + + .contact-item::before { + display: none !important; + } + + .contact-item:hover { + transform: none; + } +} diff --git a/src/app/pages/contact/contact-content/link-card/link-card.component.html b/src/app/pages/contact/contact-content/link-card/link-card.component.html new file mode 100644 index 0000000..629167e --- /dev/null +++ b/src/app/pages/contact/contact-content/link-card/link-card.component.html @@ -0,0 +1,15 @@ + +
+ +
+
+
+ {{ title() }} +
+
+
+
+
diff --git a/src/app/pages/contact/contact-content/link-card/link-card.component.ts b/src/app/pages/contact/contact-content/link-card/link-card.component.ts new file mode 100644 index 0000000..ed25e67 --- /dev/null +++ b/src/app/pages/contact/contact-content/link-card/link-card.component.ts @@ -0,0 +1,13 @@ +import { Component, input } from '@angular/core'; + +@Component({ + selector: 'app-link-card', + imports: [], + templateUrl: './link-card.component.html', + styleUrl: './link-card.component.css', +}) +export class LinkCardComponent { + title = input.required(); + contact_link = input.required(); + description = input.required(); +}