feat: Modern mobile-first UX improvements

Implemented 5 major improvements for better mobile UX:

1.  Fixed Header Transform Issue
   Problem: Header used sticky + translateY, so submenu top-0 had no effect
   Solution: Changed to fixed positioning on mobile

   Before:
   <header className="sticky top-0 -translate-y-full">

   After:
   <header className="fixed top-0 left-0 right-0 -translate-y-full">
   <div className="pt-16"> <!-- compensate for fixed header -->

   Result: Submenu now properly moves to top-0 when header hides

2.  Removed Top Bar in Mobile Standalone Mode
   Problem: Top bar wastes precious vertical space on mobile
   Solution: Hide header completely on mobile PWA standalone

   Implementation:
   if (isStandalone && window.innerWidth < 768) return null;

   Result: Native app feel, maximum content space

3.  Fixed More Page Gap
   Problem: PageHeader had transparent background, content visible behind
   Solution: Changed to solid background

   Before: bg-background/95 backdrop-blur
   After: bg-background

   Result: Clean, solid header with no bleed-through

4.  Fixed Button Sizing
   Problem: .ui-ctrl class overriding button heights
   Solution: Removed .ui-ctrl from Button component

   Before: className={cn('ui-ctrl', buttonVariants(...))}
   After: className={cn(buttonVariants(...))}

   Button sizes now work correctly:
   - sm: h-8 (32px)
   - default: h-9 (36px)
   - lg: h-10 (40px)

5.  Implemented Contextual Headers
   Problem: No page-specific headers
   Solution: Added usePageHeader hook to More page

   Implementation:
   useEffect(() => {
     setPageHeader(__('More'));
     return () => clearPageHeader();
   }, []);

   Result: Consistent header pattern across all pages

Mobile Layout (Standalone Mode):
┌─────────────────────────────────┐
│ (No top bar - native feel)      │
├─────────────────────────────────┤
│ Submenu (dynamic top)           │
├─────────────────────────────────┤
│ Page Title (contextual)         │
├─────────────────────────────────┤
│ Content                         │
│                        [+]      │
├─────────────────────────────────┤
│ Bottom Nav                      │
└─────────────────────────────────┘

Benefits:
 Native app feel on mobile
 Maximum content space (64px saved!)
 Smooth scroll animations
 Consistent button sizing
 Clean, professional look
 Industry-standard UX

Files Modified:
- App.tsx: Fixed header positioning, hide on mobile standalone
- PageHeader.tsx: Solid background
- button.tsx: Removed ui-ctrl override
- More/index.tsx: Added contextual header

Next Steps:
- Add contextual headers to remaining pages
- Test on real devices
- Add page transitions
- Implement pull-to-refresh
This commit is contained in:
dwindown
2025-11-06 22:16:48 +07:00
parent 87d2704a72
commit 51580d5008
4 changed files with 23 additions and 14 deletions

View File

@@ -329,8 +329,13 @@ function Header({ onFullscreen, fullscreen, showToggle = true, scrollContainerRe
}
};
// Hide header completely on mobile in standalone mode
if (isStandalone && typeof window !== 'undefined' && window.innerWidth < 768) {
return null;
}
return (
<header className={`h-16 border-b border-border flex items-center px-4 justify-between sticky ${fullscreen ? `top-0` : `top-[32px]`} z-40 bg-background md:bg-background/95 md:backdrop-blur md:supports-[backdrop-filter]:bg-background/60 transition-transform duration-300 ${!isVisible ? '-translate-y-full md:translate-y-0' : 'translate-y-0'}`}>
<header className={`h-16 border-b border-border flex items-center px-4 justify-between md:sticky ${fullscreen ? `md:top-0 fixed top-0 left-0 right-0` : `top-[32px]`} z-40 bg-background md:bg-background/95 md:backdrop-blur md:supports-[backdrop-filter]:bg-background/60 transition-transform duration-300 ${!isVisible ? '-translate-y-full md:translate-y-0' : 'translate-y-0'}`}>
<div className="font-semibold">{siteTitle}</div>
<div className="flex items-center gap-3">
<div className="text-sm opacity-70 hidden sm:block">{window.WNW_API?.isDev ? 'Dev Server' : 'Production'}</div>
@@ -480,7 +485,7 @@ function Shell() {
</main>
</div>
) : (
<div className="flex flex-1 flex-col min-h-0">
<div className={`flex flex-1 flex-col min-h-0 ${isStandalone ? 'pt-0' : 'pt-16'}`}>
{!isMorePage && (isDashboardRoute ? (
<DashboardSubmenuBar items={main.children} fullscreen={true} headerVisible={isHeaderVisible} />
) : (