放大产品中心菜单并适配 iPad 触控
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+50
-28
@@ -46,19 +46,19 @@ function isActive(item: NavItem): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getNavLinkClass(item: NavItem) {
|
function getNavLinkClass(item: NavItem) {
|
||||||
const baseClass = 'flex items-center gap-2 px-4 py-2.5 rounded-full font-medium transition-all duration-300';
|
const baseClass = 'nav-link flex items-center gap-2 px-5 py-3 rounded-full text-base font-semibold transition-all duration-300 touch-manipulation select-none';
|
||||||
if (isActive(item)) {
|
if (isActive(item)) {
|
||||||
return `${baseClass} bg-primary text-white shadow-md`;
|
return `${baseClass} bg-primary text-white shadow-md`;
|
||||||
}
|
}
|
||||||
return `${baseClass} text-gray-600 hover:text-primary hover:bg-primary/10`;
|
return `${baseClass} text-gray-600`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMobileNavLinkClass(item: NavItem) {
|
function getMobileNavLinkClass(item: NavItem) {
|
||||||
const baseClass = 'flex flex-col items-center justify-center py-2 px-2 min-w-[4.5rem] rounded-xl transition-all duration-300';
|
const baseClass = 'flex flex-col items-center justify-center py-2.5 px-3 min-w-[5.5rem] rounded-xl transition-all duration-300 touch-manipulation select-none';
|
||||||
if (isActive(item)) {
|
if (isActive(item)) {
|
||||||
return `${baseClass} bg-primary text-white`;
|
return `${baseClass} bg-primary text-white`;
|
||||||
}
|
}
|
||||||
return `${baseClass} text-gray-600 hover:bg-primary/10`;
|
return `${baseClass} text-gray-600`;
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -85,25 +85,25 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
<i class="fa fa-angle-down text-xs ml-0.5 transition-transform duration-200" data-dropdown-chevron></i>
|
<i class="fa fa-angle-down text-xs ml-0.5 transition-transform duration-200" data-dropdown-chevron></i>
|
||||||
</button>
|
</button>
|
||||||
<div class="absolute top-full left-1/2 -translate-x-1/2 pt-2 opacity-0 invisible transition-all duration-200 z-50"
|
<div class="absolute top-full left-1/2 -translate-x-1/2 pt-3 opacity-0 invisible transition-all duration-200 z-50"
|
||||||
data-dropdown-panel role="menu">
|
data-dropdown-panel role="menu">
|
||||||
<div class="bg-white rounded-2xl shadow-xl border border-gray-100 p-3 w-[600px]">
|
<div class="bg-white rounded-2xl shadow-xl border border-gray-100 p-4 w-[760px]">
|
||||||
<div class="grid grid-cols-3 gap-2">
|
<div class="grid grid-cols-3 gap-3">
|
||||||
{item.children.map(child => (
|
{item.children.map(child => (
|
||||||
<a href={child.href} role="menuitem"
|
<a href={child.href} role="menuitem"
|
||||||
class={`group flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all ${
|
class={`menu-item group flex items-center gap-3.5 px-4 py-3.5 rounded-xl transition-all touch-manipulation select-none ${
|
||||||
child.id === activeNav
|
child.id === activeNav
|
||||||
? 'bg-primary text-white'
|
? 'bg-primary text-white'
|
||||||
: 'text-gray-700 hover:bg-primary/10 hover:text-primary'
|
: 'text-gray-700'
|
||||||
}`}>
|
}`}>
|
||||||
<span class={`w-9 h-9 rounded-lg flex items-center justify-center shrink-0 ${
|
<span class={`menu-item-icon w-12 h-12 rounded-xl flex items-center justify-center shrink-0 transition-colors ${
|
||||||
child.id === activeNav
|
child.id === activeNav
|
||||||
? 'bg-white/20 text-white'
|
? 'bg-white/20 text-white'
|
||||||
: 'bg-primary/10 text-primary group-hover:bg-primary group-hover:text-white'
|
: 'bg-primary/10 text-primary'
|
||||||
}`}>
|
}`}>
|
||||||
<i class={`fa ${child.icon} text-base`}></i>
|
<i class={`fa ${child.icon} text-xl`}></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm font-semibold whitespace-nowrap">{child.label}</span>
|
<span class="text-base font-semibold whitespace-nowrap">{child.label}</span>
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -142,19 +142,19 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
class={getMobileNavLinkClass(item)}
|
class={getMobileNavLinkClass(item)}
|
||||||
aria-haspopup="true" aria-expanded="false"
|
aria-haspopup="true" aria-expanded="false"
|
||||||
data-mobile-dropdown-trigger>
|
data-mobile-dropdown-trigger>
|
||||||
<i class={`fa ${item.icon} text-lg mb-1`}></i>
|
<i class={`fa ${item.icon} text-xl mb-1`}></i>
|
||||||
<span class="text-xs font-medium whitespace-nowrap">{item.label}</span>
|
<span class="text-sm font-semibold whitespace-nowrap">{item.label}</span>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<a href={item.href} class={getMobileNavLinkClass(item)}>
|
<a href={item.href} class={getMobileNavLinkClass(item)}>
|
||||||
<i class={`fa ${item.icon} text-lg mb-1`}></i>
|
<i class={`fa ${item.icon} text-xl mb-1`}></i>
|
||||||
<span class="text-xs font-medium whitespace-nowrap">{item.label}</span>
|
<span class="text-sm font-semibold whitespace-nowrap">{item.label}</span>
|
||||||
</a>
|
</a>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<a href="/#contact-info" class="flex items-center justify-center py-2 px-3 bg-primary text-white rounded-xl min-w-[3rem] ml-1">
|
<a href="/#contact-info" class="flex items-center justify-center py-2.5 px-3.5 bg-primary text-white rounded-xl min-w-[3.25rem] ml-1.5">
|
||||||
<i class="fa fa-phone text-lg"></i>
|
<i class="fa fa-phone text-xl"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -163,16 +163,16 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
<div id="mobile-product-panel"
|
<div id="mobile-product-panel"
|
||||||
class="lg:hidden fixed left-0 right-0 z-30 bg-white shadow-xl border-b border-gray-200 transform -translate-y-full opacity-0 pointer-events-none transition-all duration-300"
|
class="lg:hidden fixed left-0 right-0 z-30 bg-white shadow-xl border-b border-gray-200 transform -translate-y-full opacity-0 pointer-events-none transition-all duration-300"
|
||||||
style="top: 108px;" role="menu">
|
style="top: 108px;" role="menu">
|
||||||
<div class="max-w-md mx-auto px-3 py-3 grid grid-cols-3 gap-2">
|
<div class="max-w-lg mx-auto px-4 py-4 grid grid-cols-3 gap-3">
|
||||||
{navItems.find(item => item.children)?.children?.map(child => (
|
{navItems.find(item => item.children)?.children?.map(child => (
|
||||||
<a href={child.href} role="menuitem"
|
<a href={child.href} role="menuitem"
|
||||||
class={`flex flex-col items-center gap-1.5 py-2.5 px-1 rounded-xl transition-colors ${
|
class={`flex flex-col items-center gap-2 py-4 px-2 rounded-xl transition-colors touch-manipulation select-none ${
|
||||||
child.id === activeNav
|
child.id === activeNav
|
||||||
? 'bg-primary text-white'
|
? 'bg-primary text-white'
|
||||||
: 'bg-primary/5 text-gray-700 hover:bg-primary/10'
|
: 'bg-primary/5 text-gray-700'
|
||||||
}`}>
|
}`}>
|
||||||
<i class={`fa ${child.icon} text-lg ${child.id === activeNav ? 'text-white' : 'text-primary'}`}></i>
|
<i class={`fa ${child.icon} text-2xl ${child.id === activeNav ? 'text-white' : 'text-primary'}`}></i>
|
||||||
<span class={`text-[11px] font-semibold leading-tight text-center whitespace-nowrap ${child.id === activeNav ? 'text-white' : 'text-gray-700'}`}>{child.label}</span>
|
<span class={`text-sm font-semibold leading-tight text-center whitespace-nowrap ${child.id === activeNav ? 'text-white' : 'text-gray-700'}`}>{child.label}</span>
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -182,8 +182,8 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
<div id="mobile-product-backdrop"
|
<div id="mobile-product-backdrop"
|
||||||
class="lg:hidden fixed inset-0 z-20 bg-black/20 opacity-0 pointer-events-none transition-opacity duration-300"></div>
|
class="lg:hidden fixed inset-0 z-20 bg-black/20 opacity-0 pointer-events-none transition-opacity duration-300"></div>
|
||||||
|
|
||||||
<!-- Spacer for mobile to prevent content overlap (header 3.5rem + nav 2.5rem) -->
|
<!-- Spacer for mobile to prevent content overlap (header ~3.5rem + nav ~4rem) -->
|
||||||
<div class="lg:hidden h-[6rem] transition-all duration-300"></div>
|
<div class="lg:hidden h-[7.5rem] transition-all duration-300"></div>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
<Footer />
|
<Footer />
|
||||||
@@ -198,7 +198,7 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
(function() {
|
(function() {
|
||||||
var navContainer = document.getElementById('mobile-nav-container');
|
var navContainer = document.getElementById('mobile-nav-container');
|
||||||
var headerRow = document.getElementById('mobile-header-row');
|
var headerRow = document.getElementById('mobile-header-row');
|
||||||
var spacer = document.querySelector('.lg\\:hidden.h-\\[6rem\\]');
|
var spacer = document.querySelector('.lg\\:hidden.h-\\[7\\.5rem\\]');
|
||||||
var lastScrollTop = 0;
|
var lastScrollTop = 0;
|
||||||
var scrollThreshold = 50;
|
var scrollThreshold = 50;
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
}
|
}
|
||||||
// Restore spacer height
|
// Restore spacer height
|
||||||
if (spacer) {
|
if (spacer) {
|
||||||
(spacer as HTMLElement).style.height = '6rem';
|
(spacer as HTMLElement).style.height = '7.5rem';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,6 +379,28 @@ function getMobileNavLinkClass(item: NavItem) {
|
|||||||
.no-scrollbar::-webkit-scrollbar {
|
.no-scrollbar::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hover effects only on real pointer devices (avoid sticky hover on iPad/touch) */
|
||||||
|
@media (hover: hover) and (pointer: fine) {
|
||||||
|
.nav-link.text-gray-600:hover {
|
||||||
|
color: var(--color-primary, #165DFF);
|
||||||
|
background-color: rgb(22 93 255 / 0.1);
|
||||||
|
}
|
||||||
|
.menu-item.text-gray-700:hover {
|
||||||
|
background-color: rgb(22 93 255 / 0.1);
|
||||||
|
color: var(--color-primary, #165DFF);
|
||||||
|
}
|
||||||
|
.menu-item.text-gray-700:hover .menu-item-icon {
|
||||||
|
background-color: var(--color-primary, #165DFF);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Active tap feedback for touch / iPad */
|
||||||
|
.nav-link:active,
|
||||||
|
.menu-item:active {
|
||||||
|
transform: scale(0.97);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user