From 97288a41dc618c78a356a123b0e9005d67e41bc6 Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 6 Nov 2025 22:45:47 +0700 Subject: [PATCH] feat: Mobile-only contextual headers + consistent button sizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented 3 key improvements based on user feedback: 1. ✅ PageHeader Mobile-Only Problem: Contextual header showing on desktop was redundant Solution: Added md:hidden to PageHeader component Before: Desktop: Shows "Store Details" header (redundant with nav) Mobile: Shows "Store Details" header (good!) After: Desktop: No contextual header (clean!) Mobile: Shows "Store Details" header (perfect!) Result: Cleaner desktop UI, mobile gets contextual clarity 2. ✅ Contextual Headers on All Pages Problem: Dashboard and Payments pages missing contextual headers Solution: - Added usePageHeader to Dashboard - Fixed SettingsLayout to always set header (not just when onSave exists) Before: - Dashboard: No header (confusing) - Payments: No header (confusing) - Store Details: Has header (only one working) After: - Dashboard: "Dashboard" header ✓ - Payments: "Payments" header ✓ - Store Details: "Store Details" header ✓ - All settings pages: Contextual headers ✓ Result: Consistent UX across all pages! 3. ✅ Re-added .ui-ctrl to Button Problem: Removed .ui-ctrl earlier, but it's needed for mobile sizing Solution: Added .ui-ctrl back to Button component Why .ui-ctrl is Good: - Mobile: 44px height (good touch target) - Desktop: 36px height (compact, efficient) - Responsive by default - Follows UI/UX best practices Result: Buttons properly sized for touch on mobile! Mobile Layout (Final): ┌─────────────────────────────────┐ │ Dashboard │ ← Contextual header! ├─────────────────────────────────┤ │ Overview | Revenue | Orders ... │ ← Submenu ├─────────────────────────────────┤ │ Last 7 days [Refresh] │ ├─────────────────────────────────┤ │ Revenue │ │ Rp64.500 │ │ 99.9% vs previous 7 days │ │ ( + ) │ ← FAB ├─────────────────────────────────┤ │ Bottom Nav │ └─────────────────────────────────┘ Desktop Layout (Final): ┌─────────────────────────────────┐ │ Header │ ├─────────────────────────────────┤ │ Dashboard | Orders | Products │ ← Top Nav ├─────────────────────────────────┤ │ Overview | Revenue | Orders ... │ ← Submenu ├─────────────────────────────────┤ │ (No contextual header) │ ← Clean! ├─────────────────────────────────┤ │ Revenue │ │ Rp64.500 │ └─────────────────────────────────┘ Files Modified: - PageHeader.tsx: Added md:hidden for mobile-only - Dashboard/index.tsx: Added contextual header - SettingsLayout.tsx: Always set header (not just with onSave) - button.tsx: Re-added .ui-ctrl class Result: ✅ Mobile: Contextual headers on all pages ✅ Desktop: Clean, no redundant headers ✅ Buttons: Proper touch targets (44px mobile, 36px desktop) ✅ Consistent UX across all pages! 🎉 --- admin-spa/src/components/PageHeader.tsx | 3 ++- admin-spa/src/components/ui/button.tsx | 2 +- admin-spa/src/routes/Dashboard/index.tsx | 8 ++++++++ .../src/routes/Settings/components/SettingsLayout.tsx | 8 ++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/admin-spa/src/components/PageHeader.tsx b/admin-spa/src/components/PageHeader.tsx index a41b8a6..a55b5ae 100644 --- a/admin-spa/src/components/PageHeader.tsx +++ b/admin-spa/src/components/PageHeader.tsx @@ -12,8 +12,9 @@ export function PageHeader({ fullscreen = false }: PageHeaderProps) { // PageHeader is now ABOVE submenu in DOM order // z-20 ensures it stays on top when both are sticky + // Mobile-only: hidden on desktop (md:hidden) return ( -
+

{title}

diff --git a/admin-spa/src/components/ui/button.tsx b/admin-spa/src/components/ui/button.tsx index 65d4fcd..1e1144e 100644 --- a/admin-spa/src/components/ui/button.tsx +++ b/admin-spa/src/components/ui/button.tsx @@ -45,7 +45,7 @@ const Button = React.forwardRef( const Comp = asChild ? Slot : "button" return ( diff --git a/admin-spa/src/routes/Dashboard/index.tsx b/admin-spa/src/routes/Dashboard/index.tsx index 9829de5..09d3865 100644 --- a/admin-spa/src/routes/Dashboard/index.tsx +++ b/admin-spa/src/routes/Dashboard/index.tsx @@ -12,6 +12,7 @@ import { useOverviewAnalytics } from '@/hooks/useAnalytics'; import { ErrorCard } from '@/components/ErrorCard'; import { getPageLoadErrorMessage } from '@/lib/errorHandling'; import { useFABConfig } from '@/hooks/useFABConfig'; +import { usePageHeader } from '@/contexts/PageHeaderContext'; // Dummy data for visualization const DUMMY_DATA = { @@ -160,12 +161,19 @@ function MetricCard({ title, value, change, icon: Icon, format = 'number', perio export default function Dashboard() { useFABConfig('dashboard'); // Add FAB for quick actions + const { setPageHeader, clearPageHeader } = usePageHeader(); const { period } = useDashboardPeriod(); const store = getStoreCurrency(); const [hoverIndex, setHoverIndex] = useState(undefined); const [chartMetric, setChartMetric] = useState<'both' | 'revenue' | 'orders'>('both'); const chartRef = useRef(null); + // Set contextual header + useEffect(() => { + setPageHeader(__('Dashboard')); + return () => clearPageHeader(); + }, [setPageHeader, clearPageHeader]); + // Fetch real data or use dummy data based on toggle const { data, isLoading, error, refetch } = useOverviewAnalytics(DUMMY_DATA); diff --git a/admin-spa/src/routes/Settings/components/SettingsLayout.tsx b/admin-spa/src/routes/Settings/components/SettingsLayout.tsx index b2208ce..ab6e095 100644 --- a/admin-spa/src/routes/Settings/components/SettingsLayout.tsx +++ b/admin-spa/src/routes/Settings/components/SettingsLayout.tsx @@ -55,12 +55,16 @@ export function SettingsLayout({ )} ); + } else if (action) { + // If there's a custom action, use it + setPageHeader(title, action); } else { - clearPageHeader(); + // Always set the title, even without action + setPageHeader(title); } return () => clearPageHeader(); - }, [title, onSave, isSaving, isLoading, saveLabel]); + }, [title, onSave, isSaving, isLoading, saveLabel, action, setPageHeader, clearPageHeader]); return (