update hamburger menu
This commit is contained in:
parent
284c6b5c96
commit
afe04e6f67
2 changed files with 464 additions and 194 deletions
|
|
@ -3,25 +3,33 @@
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
position: sticky;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 1001;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
|
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|
||||||
background: rgba(0, 0, 0, 0.85);
|
background: rgba(0, 0, 0, 0.82);
|
||||||
|
|
||||||
backdrop-filter: blur(14px);
|
backdrop-filter: blur(16px);
|
||||||
-webkit-backdrop-filter: blur(14px);
|
-webkit-backdrop-filter: blur(16px);
|
||||||
|
|
||||||
border-bottom: 1px solid var(--color-line);
|
border-bottom: 1px solid var(--color-line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.headerSpacer {
|
||||||
|
width: 100%;
|
||||||
|
height: 90px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
LOGO
|
LOGO
|
||||||
========================= */
|
========================= */
|
||||||
|
|
@ -61,21 +69,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
LANG TOGGLE
|
LANG TOGGLE (Header)
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
.langToggle {
|
.langToggle {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 4px;
|
gap: 5px;
|
||||||
height: 32px;
|
height: 34px;
|
||||||
padding: 0 12px;
|
padding: 0 14px;
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-size: 11.5px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
@ -92,20 +100,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.langToggleDot {
|
.langToggleDot {
|
||||||
width: 5px;
|
width: 6px;
|
||||||
height: 5px;
|
height: 6px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #3b82f6;
|
background: #3b82f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobileLangRow {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: var(--space-lg);
|
|
||||||
padding-top: var(--space-md);
|
|
||||||
border-top: 1px solid var(--color-line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
DESKTOP NAV
|
DESKTOP NAV
|
||||||
========================= */
|
========================= */
|
||||||
|
|
@ -113,12 +113,9 @@
|
||||||
.desktopNav ul {
|
.desktopNav ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
gap: var(--space-lg);
|
gap: var(--space-lg);
|
||||||
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,34 +126,24 @@
|
||||||
|
|
||||||
.desktopNav a {
|
.desktopNav a {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
|
|
||||||
color: var(--color-muted);
|
color: var(--color-muted);
|
||||||
|
|
||||||
font-size: var(--fs-nav);
|
font-size: var(--fs-nav);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
transition: color 0.25s ease;
|
transition: color 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktopNav a::after {
|
.desktopNav a::after {
|
||||||
content: "";
|
content: "";
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
|
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
|
||||||
background: var(--color-text);
|
background: var(--color-text);
|
||||||
|
|
||||||
transition: width 0.3s ease;
|
transition: width 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,129 +156,325 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
HAMBURGER
|
HAMBURGER BUTTON
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
.hamburger {
|
.hamburger {
|
||||||
display: none;
|
display: none;
|
||||||
|
align-items: center;
|
||||||
position: relative;
|
justify-content: center;
|
||||||
|
width: 42px;
|
||||||
width: 34px;
|
height: 42px;
|
||||||
height: 24px;
|
|
||||||
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
background: transparent;
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
border: 0;
|
border-radius: 12px;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: background 0.2s ease, border-color 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger span {
|
.hamburger:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger.active {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburgerBox {
|
||||||
|
position: relative;
|
||||||
|
width: 20px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburgerLine {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
border-radius: 10px;
|
|
||||||
|
|
||||||
background: var(--color-text);
|
background: var(--color-text);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
transition:
|
opacity 0.2s ease;
|
||||||
transform 0.3s ease,
|
|
||||||
opacity 0.3s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger span:nth-child(1) {
|
.hamburgerLine:nth-child(1) {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger span:nth-child(2) {
|
.hamburgerLine:nth-child(2) {
|
||||||
top: 50%;
|
top: 6px;
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger span:nth-child(3) {
|
.hamburgerLine:nth-child(3) {
|
||||||
bottom: 0;
|
top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.active span:nth-child(1) {
|
.hamburger.active .hamburgerLine:nth-child(1) {
|
||||||
transform: translateY(11px) rotate(45deg);
|
transform: translateY(6px) rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.active span:nth-child(2) {
|
.hamburger.active .hamburgerLine:nth-child(2) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(10px);
|
transform: scaleX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger.active span:nth-child(3) {
|
.hamburger.active .hamburgerLine:nth-child(3) {
|
||||||
transform: translateY(-11px) rotate(-45deg);
|
transform: translateY(-6px) rotate(-45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
MOBILE MENU
|
MOBILE BACKDROP
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.mobileBackdrop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.mobileBackdrop {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 998;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.35s ease, visibility 0.35s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileBackdrop.active {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
MOBILE MENU DRAWER
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
.mobileMenu {
|
.mobileMenu {
|
||||||
position: fixed;
|
display: none;
|
||||||
top: 90px;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100vh - 90px);
|
|
||||||
|
|
||||||
padding: var(--space-2xl) var(--container-padding);
|
|
||||||
|
|
||||||
background: var(--color-bg);
|
|
||||||
|
|
||||||
transform: translateX(100%);
|
|
||||||
|
|
||||||
transition: transform 0.45s cubic-bezier(0.32, 0.72, 0, 1);
|
|
||||||
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobileMenu.active {
|
@media (max-width: 768px) {
|
||||||
transform: translateX(0);
|
.mobileMenu {
|
||||||
}
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100dvh;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
.mobileMenu ul {
|
background: rgba(8, 8, 8, 0.94);
|
||||||
display: flex;
|
backdrop-filter: blur(28px);
|
||||||
flex-direction: column;
|
-webkit-backdrop-filter: blur(28px);
|
||||||
|
|
||||||
gap: var(--space-md);
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
|
||||||
margin: 0;
|
transition: opacity 0.35s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
padding: 0;
|
transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
|
visibility 0.35s ease;
|
||||||
|
|
||||||
list-style: none;
|
overflow-y: auto;
|
||||||
}
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
.mobileMenu li {
|
.mobileMenu.active {
|
||||||
margin: 0;
|
opacity: 1;
|
||||||
padding: 0;
|
visibility: visible;
|
||||||
}
|
pointer-events: auto;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
.mobileMenu a {
|
.mobileMenuInner {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: calc(70px + var(--space-md)) var(--container-padding) max(var(--space-lg), env(safe-area-inset-bottom, 24px));
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
color: var(--color-text);
|
/* Nav items */
|
||||||
|
.mobileNavList {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
font-size: var(--fs-display);
|
.mobileNavItem {
|
||||||
font-weight: 600;
|
margin: 0;
|
||||||
line-height: 1;
|
padding: 0;
|
||||||
letter-spacing: -0.04em;
|
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(14px);
|
||||||
|
transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
|
transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
text-decoration: none;
|
.mobileMenu.active .mobileNavItem {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
transition: color 0.25s ease;
|
.mobileNavLink {
|
||||||
}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 20px 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-text);
|
||||||
|
transition: color 0.2s ease, transform 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.mobileMenu a:hover {
|
.mobileNavLink:active {
|
||||||
color: var(--color-muted);
|
opacity: 0.7;
|
||||||
|
transform: translateX(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileNavNum {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-faint);
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileNavText {
|
||||||
|
font-size: clamp(24px, 6vw, 32px);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileNavArrow {
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 22px;
|
||||||
|
color: var(--color-faint);
|
||||||
|
transition: transform 0.2s ease, color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileNavLink:hover .mobileNavArrow,
|
||||||
|
.mobileNavLink:active .mobileNavArrow {
|
||||||
|
color: #93c5fd;
|
||||||
|
transform: translate(2px, -2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extra / Action section */
|
||||||
|
.mobileExtra {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--space-md);
|
||||||
|
margin-top: var(--space-xl);
|
||||||
|
padding-top: var(--space-md);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(14px);
|
||||||
|
transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
|
transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileMenu.active .mobileExtra {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileActionGroup {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileResumeBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
height: 48px;
|
||||||
|
padding: 0 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: transform 0.2s ease, background 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileResumeBtn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
background: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileLangBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
height: 44px;
|
||||||
|
padding: 0 16px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
border-radius: 12px;
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: background 0.2s ease, border-color 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileLangBtn:active {
|
||||||
|
background: rgba(37, 99, 235, 0.15);
|
||||||
|
border-color: rgba(59, 130, 246, 0.4);
|
||||||
|
color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileSocials {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileSocialLink {
|
||||||
|
flex: 1;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 38px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--color-muted);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileSocialLink:active {
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
|
|
@ -299,7 +482,8 @@
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
@media (min-width: 1600px) {
|
@media (min-width: 1600px) {
|
||||||
.header {
|
.header,
|
||||||
|
.headerSpacer {
|
||||||
height: 110px;
|
height: 110px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +493,8 @@
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
.header {
|
.header,
|
||||||
|
.headerSpacer {
|
||||||
height: 80px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,7 +508,8 @@
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.header {
|
.header,
|
||||||
|
.headerSpacer {
|
||||||
height: 70px;
|
height: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,12 +518,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger {
|
.hamburger {
|
||||||
display: block;
|
display: inline-flex;
|
||||||
}
|
|
||||||
|
|
||||||
.mobileMenu {
|
|
||||||
top: 70px;
|
|
||||||
height: calc(100vh - 70px);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,23 +527,16 @@
|
||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.header {
|
.header,
|
||||||
|
.headerSpacer {
|
||||||
height: 64px;
|
height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
font-size: 25px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hamburger {
|
.mobileMenuInner {
|
||||||
width: 29px;
|
padding-top: calc(64px + var(--space-sm));
|
||||||
height: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobileMenu {
|
|
||||||
top: 64px;
|
|
||||||
height: calc(100vh - 64px);
|
|
||||||
|
|
||||||
padding-top: var(--space-lg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,10 +30,16 @@ export const Header = () => {
|
||||||
switchHref = `${switchHref}/`;
|
switchHref = `${switchHref}/`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resumeHref =
|
||||||
|
locale === "en"
|
||||||
|
? "/Nikita_Egorov_Resume_EN.pdf"
|
||||||
|
: "/Nikita_Egorov_Resume_RU.pdf";
|
||||||
|
const resumeLabel = locale === "en" ? "Resume (PDF)" : "Резюме (PDF)";
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ label: dict.nav.about, href: `/${locale}/#about` },
|
{ num: "01", label: dict.nav.about, href: `/${locale}/#about` },
|
||||||
{ label: dict.nav.projects, href: `/${locale}/projects/` },
|
{ num: "02", label: dict.nav.projects, href: `/${locale}/projects/` },
|
||||||
{ label: dict.nav.contact, href: `/${locale}/#contact` },
|
{ num: "03", label: dict.nav.contact, href: `/${locale}/#contact` },
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -45,13 +51,20 @@ export const Header = () => {
|
||||||
if (window.innerWidth > 768) setOpen(false);
|
if (window.innerWidth > 768) setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
document.documentElement.classList.toggle("no-scroll", open);
|
if (open) {
|
||||||
|
document.documentElement.classList.add("no-scroll");
|
||||||
|
document.body.classList.add("no-scroll");
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove("no-scroll");
|
||||||
|
document.body.classList.remove("no-scroll");
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("keydown", onKeyDown);
|
window.addEventListener("keydown", onKeyDown);
|
||||||
window.addEventListener("resize", onResize);
|
window.addEventListener("resize", onResize);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.documentElement.classList.remove("no-scroll");
|
document.documentElement.classList.remove("no-scroll");
|
||||||
|
document.body.classList.remove("no-scroll");
|
||||||
window.removeEventListener("keydown", onKeyDown);
|
window.removeEventListener("keydown", onKeyDown);
|
||||||
window.removeEventListener("resize", onResize);
|
window.removeEventListener("resize", onResize);
|
||||||
};
|
};
|
||||||
|
|
@ -60,78 +73,161 @@ export const Header = () => {
|
||||||
const close = () => setOpen(false);
|
const close = () => setOpen(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={styles.header}>
|
<>
|
||||||
<div className="cont-header">
|
<header className={styles.header}>
|
||||||
<div className={styles.left}>
|
<div className="cont-header">
|
||||||
<Link href={`/${locale}/`} className={styles.logo} onClick={close}>
|
<div className={styles.left}>
|
||||||
Autli
|
<Link href={`/${locale}/`} className={styles.logo} onClick={close}>
|
||||||
</Link>
|
Autli
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.right}>
|
||||||
|
<nav className={styles.desktopNav} aria-label="Основная навигация">
|
||||||
|
<ul>
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<li key={item.href}>
|
||||||
|
<Link href={item.href}>{item.label}</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Language Switcher */}
|
||||||
|
<Link
|
||||||
|
href={switchHref}
|
||||||
|
className={styles.langToggle}
|
||||||
|
aria-label={`Switch to ${targetLocale === "en" ? "English" : "Russian"}`}
|
||||||
|
data-cursor-hover
|
||||||
|
>
|
||||||
|
<span className={styles.langToggleDot} aria-hidden="true" />
|
||||||
|
<span>{targetLabel}</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* Hamburger Button */}
|
||||||
|
<button
|
||||||
|
className={`${styles.hamburger} ${open ? styles.active : ""}`}
|
||||||
|
type="button"
|
||||||
|
aria-label={open ? "Закрыть меню" : "Открыть меню"}
|
||||||
|
aria-expanded={open}
|
||||||
|
onClick={() => setOpen((value) => !value)}
|
||||||
|
>
|
||||||
|
<div className={styles.hamburgerBox}>
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
<span className={styles.hamburgerLine} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div className={styles.right}>
|
{/* Spacer to preserve normal document flow with fixed header */}
|
||||||
<nav className={styles.desktopNav} aria-label="Основная навигация">
|
<div className={styles.headerSpacer} aria-hidden="true" />
|
||||||
<ul>
|
|
||||||
{navItems.map((item) => (
|
|
||||||
<li key={item.href}>
|
|
||||||
<Link href={item.href}>{item.label}</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Modern Single-Button Language Switcher */}
|
{/* Mobile Drawer Navigation */}
|
||||||
<Link
|
<div
|
||||||
href={switchHref}
|
className={`${styles.mobileBackdrop} ${open ? styles.active : ""}`}
|
||||||
className={styles.langToggle}
|
onClick={close}
|
||||||
aria-label={`Switch to ${targetLocale === "en" ? "English" : "Russian"}`}
|
aria-hidden="true"
|
||||||
data-cursor-hover
|
/>
|
||||||
>
|
|
||||||
<span className={styles.langToggleDot} aria-hidden="true" />
|
|
||||||
<span>{targetLabel}</span>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{/* Hamburger */}
|
|
||||||
<button
|
|
||||||
className={`${styles.hamburger} ${open ? styles.active : ""}`}
|
|
||||||
type="button"
|
|
||||||
aria-label={open ? "Закрыть меню" : "Открыть меню"}
|
|
||||||
aria-expanded={open}
|
|
||||||
onClick={() => setOpen((value) => !value)}
|
|
||||||
>
|
|
||||||
<span />
|
|
||||||
<span />
|
|
||||||
<span />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav
|
<nav
|
||||||
className={`${styles.mobileMenu} ${open ? styles.active : ""}`}
|
className={`${styles.mobileMenu} ${open ? styles.active : ""}`}
|
||||||
aria-label="Мобильная навигация"
|
aria-label="Мобильная навигация"
|
||||||
|
aria-hidden={!open}
|
||||||
>
|
>
|
||||||
<ul>
|
<div className={styles.mobileMenuInner}>
|
||||||
{navItems.map((item) => (
|
<ul className={styles.mobileNavList}>
|
||||||
<li key={item.href}>
|
{navItems.map((item, idx) => (
|
||||||
<Link href={item.href} onClick={close}>
|
<li
|
||||||
{item.label}
|
key={item.href}
|
||||||
</Link>
|
className={styles.mobileNavItem}
|
||||||
</li>
|
style={{ transitionDelay: open ? `${0.06 + idx * 0.05}s` : "0s" }}
|
||||||
))}
|
>
|
||||||
</ul>
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
onClick={close}
|
||||||
|
className={styles.mobileNavLink}
|
||||||
|
>
|
||||||
|
<span className={styles.mobileNavNum}>{item.num}</span>
|
||||||
|
<span className={styles.mobileNavText}>{item.label}</span>
|
||||||
|
<span className={styles.mobileNavArrow} aria-hidden="true">
|
||||||
|
↗
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div className={styles.mobileLangRow}>
|
<div
|
||||||
<Link
|
className={styles.mobileExtra}
|
||||||
href={switchHref}
|
style={{ transitionDelay: open ? "0.22s" : "0s" }}
|
||||||
className={styles.langToggle}
|
|
||||||
onClick={close}
|
|
||||||
aria-label={`Switch to ${targetLocale === "en" ? "English" : "Russian"}`}
|
|
||||||
>
|
>
|
||||||
<span className={styles.langToggleDot} aria-hidden="true" />
|
<div className={styles.mobileActionGroup}>
|
||||||
<span>{targetLabel}</span>
|
<a
|
||||||
</Link>
|
href={resumeHref}
|
||||||
|
download
|
||||||
|
className={styles.mobileResumeBtn}
|
||||||
|
onClick={close}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
||||||
|
<polyline points="7 10 12 15 17 10" />
|
||||||
|
<line x1="12" y1="15" x2="12" y2="3" />
|
||||||
|
</svg>
|
||||||
|
<span>{resumeLabel}</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href={switchHref}
|
||||||
|
className={styles.mobileLangBtn}
|
||||||
|
onClick={close}
|
||||||
|
aria-label={`Switch to ${targetLocale === "en" ? "English" : "Russian"}`}
|
||||||
|
>
|
||||||
|
<span className={styles.langToggleDot} aria-hidden="true" />
|
||||||
|
<span>{locale === "ru" ? "English version" : "Русская версия"} ({targetLabel})</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.mobileSocials}>
|
||||||
|
<a
|
||||||
|
href="https://t.me/autli"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className={styles.mobileSocialLink}
|
||||||
|
>
|
||||||
|
Telegram ↗
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://github.com/autli"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className={styles.mobileSocialLink}
|
||||||
|
>
|
||||||
|
GitHub ↗
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="mailto:ne60201@gmail.com"
|
||||||
|
className={styles.mobileSocialLink}
|
||||||
|
>
|
||||||
|
Email ↗
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue