feat(ui): add responsive mobile menu with animated hamburger icon
- Add hamburger icon that morphs to X when menu is open - Full-screen mobile menu overlay with backdrop blur - Staggered fade-in animation for menu items - Desktop navigation unchanged (hidden on mobile) - Close menu via X button, backdrop click, or ESC key 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -34,9 +34,12 @@
|
||||
--leading-relaxed: 1.625;
|
||||
--radius-sm: 0.25rem;
|
||||
--radius-lg: 0.5rem;
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--animate-bounce: bounce 1s infinite;
|
||||
--blur-md: 12px;
|
||||
--blur-lg: 16px;
|
||||
--blur-xl: 24px;
|
||||
--default-transition-duration: 150ms;
|
||||
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--default-font-family: var(--font-sans);
|
||||
@@ -238,6 +241,9 @@
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
.z-\[300\] {
|
||||
z-index: 300;
|
||||
}
|
||||
.z-player {
|
||||
z-index: 400;
|
||||
}
|
||||
@@ -403,6 +409,14 @@
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.translate-y-0 {
|
||||
--tw-translate-y: calc(var(--spacing) * 0);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.translate-y-4 {
|
||||
--tw-translate-y: calc(var(--spacing) * 4);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.scale-90 {
|
||||
--tw-scale-x: 90%;
|
||||
--tw-scale-y: 90%;
|
||||
@@ -451,6 +465,9 @@
|
||||
.gap-6 {
|
||||
gap: calc(var(--spacing) * 6);
|
||||
}
|
||||
.gap-8 {
|
||||
gap: calc(var(--spacing) * 8);
|
||||
}
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -501,6 +518,12 @@
|
||||
background-color: color-mix(in oklab, var(--color-surface-0) 80%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-surface-0\/98 {
|
||||
background-color: var(--color-surface-0);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, var(--color-surface-0) 98%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-surface-2 {
|
||||
background-color: var(--color-surface-2);
|
||||
}
|
||||
@@ -649,6 +672,9 @@
|
||||
.opacity-10 {
|
||||
opacity: 10%;
|
||||
}
|
||||
.opacity-100 {
|
||||
opacity: 100%;
|
||||
}
|
||||
.shadow {
|
||||
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
@@ -669,6 +695,11 @@
|
||||
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
}
|
||||
.backdrop-blur-xl {
|
||||
--tw-backdrop-blur: blur(var(--blur-xl));
|
||||
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
}
|
||||
.transition {
|
||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
@@ -694,6 +725,14 @@
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
.duration-150 {
|
||||
--tw-duration: 150ms;
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
.duration-200 {
|
||||
--tw-duration: 200ms;
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
.duration-300 {
|
||||
--tw-duration: 300ms;
|
||||
transition-duration: 300ms;
|
||||
@@ -702,6 +741,14 @@
|
||||
--tw-duration: 500ms;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
.ease-in {
|
||||
--tw-ease: var(--ease-in);
|
||||
transition-timing-function: var(--ease-in);
|
||||
}
|
||||
.ease-out {
|
||||
--tw-ease: var(--ease-out);
|
||||
transition-timing-function: var(--ease-out);
|
||||
}
|
||||
.group-hover\:translate-x-1 {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
@@ -900,6 +947,11 @@
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.md\:hidden {
|
||||
@media (width >= 48rem) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.md\:grid-cols-2 {
|
||||
@media (width >= 48rem) {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
@@ -915,11 +967,6 @@
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
.md\:gap-8 {
|
||||
@media (width >= 48rem) {
|
||||
gap: calc(var(--spacing) * 8);
|
||||
}
|
||||
}
|
||||
.md\:text-4xl {
|
||||
@media (width >= 48rem) {
|
||||
font-size: var(--text-4xl);
|
||||
@@ -1057,6 +1104,43 @@ html {
|
||||
transform: scaleX(1);
|
||||
transform-origin: left;
|
||||
}
|
||||
.hamburger {
|
||||
width: 20px;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
.hamburger span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: var(--color-text-primary);
|
||||
border-radius: var(--radius-full);
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
}
|
||||
.hamburger span:nth-child(1) {
|
||||
top: 0;
|
||||
}
|
||||
.hamburger span:nth-child(2) {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.hamburger span:nth-child(3) {
|
||||
bottom: 0;
|
||||
}
|
||||
.hamburger.is-active span:nth-child(1) {
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(45deg);
|
||||
}
|
||||
.hamburger.is-active span:nth-child(2) {
|
||||
opacity: 0;
|
||||
transform: translateX(10px);
|
||||
}
|
||||
.hamburger.is-active span:nth-child(3) {
|
||||
bottom: 50%;
|
||||
transform: translateY(50%) rotate(-45deg);
|
||||
}
|
||||
.audio-player {
|
||||
background: var(--color-surface-1);
|
||||
border-top: 1px solid var(--color-border);
|
||||
@@ -1186,6 +1270,21 @@ html {
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
@property --tw-translate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-scale-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@@ -1458,20 +1557,9 @@ html {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-translate-x {
|
||||
@property --tw-ease {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-content {
|
||||
syntax: "*";
|
||||
@@ -1491,6 +1579,9 @@ html {
|
||||
@layer properties {
|
||||
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||
*, ::before, ::after, ::backdrop {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-scale-z: 1;
|
||||
@@ -1554,9 +1645,7 @@ html {
|
||||
--tw-backdrop-saturate: initial;
|
||||
--tw-backdrop-sepia: initial;
|
||||
--tw-duration: initial;
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
--tw-ease: initial;
|
||||
--tw-content: "";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user