diff --git a/services/frontend/.hermes/plans/mobile-nav-form-responsive.md b/services/frontend/.hermes/plans/mobile-nav-form-responsive.md new file mode 100644 index 00000000..ec2d0671 --- /dev/null +++ b/services/frontend/.hermes/plans/mobile-nav-form-responsive.md @@ -0,0 +1,53 @@ +# GMW Frontend — Mobile Nav + Form Controls Responsive Pass + +## Problem +Two mobile UX defects reported by user: + +1. **Mobile navbar can't navigate between pages** (`tidak bisa pindah halaman`). + - **Root cause A (click-block):** the floating chatbot FAB + (`chatbot.tsx` line ~125: `fixed right-4 bottom-5 z-50 size-11`) overlaps the + mobile bottom nav (`MobileNav` is `fixed bottom-0 z-40`). Because the FAB is + `z-50` and sits at `bottom-5` on the right, it intercepts taps on the + rightmost bottom-nav items (Voice/Media). Verified in Playwright: click on + `Media` nav item is blocked by `button[aria-label="Open neural HUD assistant"]`. + - **Root cause B (missing destinations):** `mobileNavItems` in + `src/lib/navigation.ts` filters `navItems` to only + `['/dashboard','/messages','/voice','/media']`, so `/recordings`, + `/moderation`, `/analysis` are unreachable from the mobile bottom bar. + - **Chosen design (user directive):** extend the mobile bottom bar to **all 7 + nav items**, horizontally **scrollable/flex-wrap** so they fit on narrow + screens, following the desktop sidebar's items (same set as `navItems`). + +2. **Form controls not responsive on mobile** (`perbagus textfield, dropdown, + lainnya agar responsif di mobile`). + - `Select` dropdown (`primitives/select.tsx`) is portalled w/ `fixed` + positioning computed from trigger rect only (top/left/width). On a narrow + viewport a dropdown anchored near the right edge overflows past the screen's + right edge and can be clipped/clickable-outside the visible area. Clamp + horizontally within viewport. + - `Input`/`Textarea` (`primitives/input.tsx`) use `text-sm` (14px) which on + iOS triggers auto-zoom on focus (a known mobile annoyance) and can be small + touch targets. Give inputs a comfortable mobile baseline. + +## Files touched +- `src/components/shell/mobile-nav.tsx` — use `navItems` (all 7), make the bar + scrollable on narrow widths (overflow-x-auto + snap), keep active indicator. +- `src/components/chatbot/chatbot.tsx` — raise FAB above the mobile bottom nav on + `md:hidden` (e.g. `bottom-[calc(4.75rem+env(safe-area-inset-bottom))]`), + keep `bottom-5` on `md+` so it never overlaps the nav. +- `src/lib/navigation.ts` — drop `mobileNavItems` special-case (or repoint to + `navItems`); keep `navItems` as the single source. +- `src/components/primitives/select.tsx` — clamp dropdown `left` so it stays + within viewport; cap width on narrow screens; keep max-height. +- `src/components/primitives/input.tsx` — mobile-friendly font size / touch + height (16px inputs to avoid iOS zoom; keep desktop as-is via responsive + classes). + +## Verification +- `pnpm format`, `pnpm lint` (biome clean), `pnpm build` compiles. +- Smoke on NON-PROD port (4024) — confirm free first via `ss -ltnp`. +- Playwright mobile viewport (390px): ALL 7 nav items present in bottom bar; + tapping each navigates (esp. Media rightmost item NOT blocked by FAB); FAB is + raised above the nav and no longer intercepts taps. +- Select dropdown on a 390px viewport stays fully on-screen (no right overflow). +- Commit (no trailer), push, `gh run watch`, verify all 7 live routes 200. diff --git a/services/frontend/src/app/(dashboard)/messages/view.tsx b/services/frontend/src/app/(dashboard)/messages/view.tsx index 546840b5..0d7f73fa 100644 --- a/services/frontend/src/app/(dashboard)/messages/view.tsx +++ b/services/frontend/src/app/(dashboard)/messages/view.tsx @@ -738,11 +738,7 @@ function MessageRow({ : "border-hairline bg-surface-2 hover:border-hairline-focus hover:bg-surface" }`} > - +
diff --git a/services/frontend/src/components/chatbot/chatbot.tsx b/services/frontend/src/components/chatbot/chatbot.tsx index 17e7243d..e9883555 100644 --- a/services/frontend/src/components/chatbot/chatbot.tsx +++ b/services/frontend/src/components/chatbot/chatbot.tsx @@ -122,7 +122,7 @@ export function Chatbot() { type="button" aria-label="Open neural HUD assistant" onClick={() => setOpen(true)} - className="fixed right-4 bottom-5 z-50 flex size-11 items-center justify-center rounded-full border border-signal/40 bg-surface text-signal shadow-[0_0_20px_var(--color-signal-glow)] transition-all duration-200 hover:scale-105 hover:border-signal hover:bg-signal hover:text-white" + className="fixed right-4 z-50 flex size-11 items-center justify-center rounded-full border border-signal/40 bg-surface text-signal shadow-[0_0_20px_var(--color-signal-glow)] transition-all duration-200 hover:scale-105 hover:border-signal hover:bg-signal hover:text-white bottom-[calc(4.75rem+env(safe-area-inset-bottom))] md:bottom-5" > @@ -234,7 +234,7 @@ export function Chatbot() { placeholder="Transmit instruction to core..." value={input} onChange={(e) => setInput(e.target.value)} - className="flex-1 rounded-[6px] border border-hairline bg-surface-2 px-3 py-1.5 font-mono text-xs text-ink placeholder:text-ink-faint focus:border-signal focus:outline-none" + className="min-h-[38px] flex-1 rounded-[6px] border border-hairline bg-surface-2 px-3 py-1.5 font-mono text-xs text-ink placeholder:text-ink-faint focus:border-signal focus:outline-none" />