The mobile interface is anchored by a bottom navigation bar, visible on all screens below the 1024px breakpoint. It provides single-tap access to the five primary sections of the app.
Five items arranged horizontally across the bottom of the viewport:
localStorage key aquadealers-quick-add; Expense, Cash In, Cash Out, Add Farmer and Stock Transfer start unticked. Code: src/components/layout/QuickAddMenu.tsx.The nav bar uses env(safe-area-inset-bottom) via the content-safe-bottom utility to avoid overlap with the iOS home indicator. It is hidden on desktop (≥1024px).
Sticky action bars (a page's total + Save/Review/Confirm bar) use the sticky-above-nav class from src/tailwind.css, not sticky bottom-*. On phones it sticks the bar 0.75rem above the nav (--app-bottom-nav-height + safe area). From 1024px it sticks 1rem from the bottom. Used on New Estimate, New Return, Farmer Ledger (current due), Bulk Historical Entry and Return to Supplier. A plain sticky bottom-4 bar sits under the fixed nav, and a tap on its buttons can hit the nav instead (fixed 2026-10-22).
Bill details header: back arrow and a ⋮ menu share the top row (Share on WhatsApp, Print, Download PDF, Edit, Return, Settlement Discount, Delete); under the bill number only the WhatsApp status chip (and Verify Delivery when pending) shows. Code: BillActionsMenu in src/features/billing/pages/BillDetailsPage.tsx.
Mobile billing is a 3-step wizard, each step on its own screen with a progress indicator at the top.
Product selection via category cards (Feed / Medicine) that open a modal sheet. Users can search within a category and tap a product to add it to the cart.
The cart is displayed inline below the category selector with editable quantity and price per item. A running subtotal is shown at the bottom of the item list.
Payment type selection: Credit Cash Partial. Amount input field appears for cash and partial payments with auto-calculated balance due. A date picker allows setting the bill date.
Full bill summary showing all line items, quantities, prices, and totals. A canvas-based signature pad accepts touch input for the farmer's signature.
A sticky "Create Bill" button sits at the bottom of the screen. After creation, the user is offered the option to send the bill via WhatsApp.
| Pattern | Implementation |
|---|---|
| Mobile-first | Default styles target mobile. Desktop overrides use the lg: prefix (1024px breakpoint). |
| Layout toggling | lg:hidden / hidden lg:flex to render separate mobile and desktop blocks. |
| Dashboard | Separate mobile and desktop layout components loaded per breakpoint. |
| Spacing | Fluid gutter: --page-gutter: clamp(1rem, 3vw, 1.5rem) |
| Tablet | No tablet-specific breakpoint. 768–1024px receives the mobile layout. |
| Tables | Horizontal scroll on mobile via the .tw wrapper. |
| Modals | Slide-up sheet on mobile; scale-in centered dialog on desktop. |
| Gesture | Where | Behavior |
|---|---|---|
| Date swipe | Daily Book page | Swipe left/right to navigate between dates. |
| Pull-to-refresh | List views | Triggers a React Query refetch of the current data. |
| Tap-hold | Not used | Avoided for simplicity; no long-press actions. |
| Quantity +/− | Cart items | Tap to increment/decrement. Hold for rapid change. |
| Swipe to dismiss | Not used | Standard back navigation is used instead. |
html-to-image, swapped from html2canvas 2026-09-18 to fix an oklch() color crash — see Changelog) on the main thread. Same DOM-capture approach as before, so the previously-measured 3–5 second mobile freeze likely still applies; not re-benchmarked after the swap.browser-image-compression library compresses images before upload to reduce bandwidth usage.client_ref for idempotent sync when the connection returns.