feat: Implement mobile-first navigation with bottom bar and FAB

Implemented mobile-optimized navigation structure:

1. Bottom Navigation (Mobile Only)
   - 5 items: Dashboard, Orders, Products, Customers, More
   - Fixed at bottom, always visible
   - Thumb-friendly positioning
   - Active state indication
   - Hidden on desktop (md:hidden)

2. More Menu Page
   - Overflow menu for Coupons and Settings
   - Clean list layout with icons
   - Descriptions for each item
   - Chevron indicators

3. FAB (Floating Action Button)
   - Context-aware system via FABContext
   - Fixed bottom-right (72px from bottom)
   - Hidden on desktop (md:hidden)
   - Ready for contextual actions per page

4. FAB Context System
   - Global state for FAB configuration
   - setFAB() / clearFAB() methods
   - Supports icon, label, onClick, visibility
   - Allows pages to control FAB behavior

5. Layout Updates
   - Added pb-14 to main for bottom nav spacing
   - BottomNav and FAB in mobile fullscreen layout
   - Wrapped app with FABProvider

Structure (Mobile):
┌─────────────────────────────────┐
│ App Bar (will hide on scroll)   │
├─────────────────────────────────┤
│ Page Header (sticky, contextual)│
├─────────────────────────────────┤
│ Submenu (sticky)                │
├─────────────────────────────────┤
│ Content (scrollable)            │
│                        [+] FAB  │
├─────────────────────────────────┤
│ Bottom Nav (fixed)              │
└─────────────────────────────────┘

Next Steps:
- Implement scroll-hide for app bar
- Add contextual FAB per page
- Test on real devices

Files Created:
- BottomNav.tsx: Bottom navigation component
- More/index.tsx: More menu page
- FABContext.tsx: FAB state management
- FAB.tsx: Floating action button component
- useScrollDirection.ts: Scroll detection hook

Files Modified:
- App.tsx: Added bottom nav, FAB, More route, providers
This commit is contained in:
dwindown
2025-11-06 20:21:12 +07:00
parent 4be283c4a4
commit 76624bb473
6 changed files with 261 additions and 6 deletions

View File

@@ -30,7 +30,10 @@ import SubmenuBar from './components/nav/SubmenuBar';
import DashboardSubmenuBar from './components/nav/DashboardSubmenuBar';
import { DashboardProvider } from '@/contexts/DashboardContext';
import { PageHeaderProvider } from '@/contexts/PageHeaderContext';
import { FABProvider } from '@/contexts/FABContext';
import { PageHeader } from '@/components/PageHeader';
import { BottomNav } from '@/components/nav/BottomNav';
import { FAB } from '@/components/FAB';
import { useActiveSection } from '@/hooks/useActiveSection';
import { NAV_TREE_VERSION } from '@/nav/tree';
import { __ } from '@/lib/i18n';
@@ -192,6 +195,7 @@ import SettingsIndex from '@/routes/Settings';
import SettingsStore from '@/routes/Settings/Store';
import SettingsPayments from '@/routes/Settings/Payments';
import SettingsShipping from '@/routes/Settings/Shipping';
import MorePage from '@/routes/More';
// Addon Route Component - Dynamically loads addon components
function AddonRoute({ config }: { config: any }) {
@@ -369,6 +373,9 @@ function AppRoutes() {
{/* Customers */}
<Route path="/customers" element={<CustomersIndex />} />
{/* More */}
<Route path="/more" element={<MorePage />} />
{/* Settings */}
<Route path="/settings" element={<SettingsIndex />} />
<Route path="/settings/store" element={<SettingsStore />} />
@@ -436,12 +443,14 @@ function Shell() {
) : (
<SubmenuBar items={main.children} fullscreen={true} />
)}
<main className="flex-1 flex flex-col min-h-0 min-w-0">
<main className="flex-1 flex flex-col min-h-0 min-w-0 pb-14">
<PageHeader fullscreen={true} />
<div className="flex-1 overflow-auto p-4 min-w-0">
<AppRoutes />
</div>
</main>
<BottomNav />
<FAB />
</div>
)
) : (
@@ -510,11 +519,13 @@ function AuthWrapper() {
}
return (
<PageHeaderProvider>
<DashboardProvider>
<Shell />
</DashboardProvider>
</PageHeaderProvider>
<FABProvider>
<PageHeaderProvider>
<DashboardProvider>
<Shell />
</DashboardProvider>
</PageHeaderProvider>
</FABProvider>
);
}