From 089c114019e192e2a0cd4c6e3d24319676d78e7e Mon Sep 17 00:00:00 2001 From: Amir Husayn Panahifar Date: Sun, 18 Oct 2026 10:51:37 +0330 Subject: [PATCH] =?UTF-8?q?feat:=20mobile-first=20responsive=20overhaul=20?= =?UTF-8?q?=E2=80=94=20safe=20areas,=20touch=20targets,=20bottom=20sheet,?= =?UTF-8?q?=20bottom=20nav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Viewport: - Add `viewport` export with `viewport-fit=cover` (enables CSS safe-area-inset-* on bezel-less iOS/Android) and `interactive-widget=resizes-content` (prevents layout jumps from virtual keyboard open/close) iOS zoom prevention: - input.tsx, textarea.tsx: change text-sm (14px) → text-base sm:text-sm (16px) on mobile; iOS Safari auto-zooms any input with font-size < 16px Touch targets: - button.tsx: default h-10 → h-11 (44px), sm h-8 → h-9 (36px), icon h-10→h-11 matching the 44×44px iOS HIG and WCAG 2.5.5 minimum - Add touch-manipulation to buttons, inputs, textarea to eliminate 300ms tap delay Dialog → mobile bottom sheet: - On mobile (< 640px): anchored to bottom with full width, rounded top corners, slide-in-from-bottom / slide-out-to-bottom animation, drag handle affordance, max-h-[90svh] + overflow-y-auto to prevent viewport overflow - Safe area padding: pb-[max(1.25rem,env(safe-area-inset-bottom))] - On desktop (sm+): unchanged centered modal with zoom animation - Close button gets a 32×32 tap area on mobile Mobile navigation: - New bottom-nav.tsx: persistent 3-tab bottom bar (مسیر/مرکز/لیگ) shown below md: breakpoint, hidden on desktop; 56px height + safe-area-inset-bottom; active tab gets heavier stroke and scale - Only shown for authenticated non-admin users - app-shell.tsx: injects BottomNav; main content gets dynamic padding-bottom to clear the bar (56px + safe area) on mobile, reverts to py-10 on md: - Footer: safe-area-inset-bottom padding so content clears iPhone home indicator Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/app/layout.tsx | 9 ++++- frontend/src/components/app-shell.tsx | 13 +++++-- frontend/src/components/bottom-nav.tsx | 47 +++++++++++++++++++++++++ frontend/src/components/ui/button.tsx | 8 ++--- frontend/src/components/ui/dialog.tsx | 17 +++++++-- frontend/src/components/ui/input.tsx | 3 +- frontend/src/components/ui/textarea.tsx | 3 +- 7 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 frontend/src/components/bottom-nav.tsx diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index dd4fe69..109e9c9 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import localFont from "next/font/local"; import "./globals.css"; import { Providers } from "@/components/providers"; @@ -37,6 +37,13 @@ export const metadata: Metadata = { description: "مسیر یادگیری واقعی پرگار", }; +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + viewportFit: "cover", + interactiveWidget: "resizes-content", +}; + export default function RootLayout({ children }: { children: React.ReactNode }) { return ( )} -
+
{allowChildren ? children : null}
-