From ab5444ee94b456fd8246cdf63d0e8830fb6a1e56 Mon Sep 17 00:00:00 2001 From: Andy Charlwood Date: Sun, 15 Feb 2026 20:43:48 +0000 Subject: [PATCH] feat: US-011 - Mobile full-screen chat panel --- Ralph/prd.json | 76 +++++++++++++++++++++++++++++++++++ Ralph/progress.txt | 24 +++++++++++ src/components/ChatWidget.tsx | 25 +++++++----- 3 files changed, 114 insertions(+), 11 deletions(-) diff --git a/Ralph/prd.json b/Ralph/prd.json index 38185e3..6775888 100644 --- a/Ralph/prd.json +++ b/Ralph/prd.json @@ -195,6 +195,82 @@ "priority": 10, "passes": true, "notes": "The action routing needs to flow from ChatWidget up to DashboardLayout. Add an onAction prop to ChatWidget (same pattern as CommandPalette). DashboardLayout passes handlePaletteAction to ChatWidget. Export iconByType and iconColorStyles from CommandPalette (or extract to a shared module) so ChatWidget can reuse them." + }, + { + "id": "US-011", + "title": "Mobile full-screen chat panel", + "description": "As a mobile visitor, I want the chat panel to be a full-screen overlay so it's easy to use on small screens.", + "acceptanceCriteria": [ + "Below md breakpoint (768px), chat panel renders as full-screen overlay using position: fixed; inset: 0 with 100dvh height", + "Full-screen mode has the existing header with close button (no visual change needed, just full-width)", + "Floating chat button is hidden (display: none or opacity: 0) while panel is open on mobile (<768px)", + "Above 768px, existing panel behavior is unchanged (380px wide, anchored bottom-right, max-height 480px)", + "Panel open/close animation still respects prefers-reduced-motion", + "Safe area insets applied via env(safe-area-inset-*) for notched devices", + "Input area stays pinned to bottom of screen on mobile", + "Typecheck passes", + "Verify in browser using dev-browser skill" + ], + "priority": 11, + "passes": true, + "notes": "The current ChatWidget already has some mobile handling (bottom-sheet style at <640px). This story changes the breakpoint to 768px (md) and makes it truly full-screen instead of 85vh. Use 100dvh (dynamic viewport height) to account for mobile browser chrome. The floating button visibility can be controlled by combining isOpen state with a CSS media query or a useMediaQuery hook. The
{/* Header */} @@ -536,18 +542,15 @@ export function ChatWidget({ onAction }: ChatWidgetProps) { )} - {/* Floating chat button */} + {/* Floating chat button — hidden on mobile when panel is open */} setIsOpen((prev) => !prev)} aria-label={isOpen ? 'Close chat' : 'Open chat'} - className="fixed z-[90] cursor-pointer bottom-4 right-4 h-10 w-10 sm:bottom-6 sm:right-6 sm:h-12 sm:w-12" + className={`fixed z-[90] cursor-pointer flex items-center justify-center bottom-4 right-4 h-10 w-10 md:bottom-6 md:right-6 md:h-12 md:w-12${isOpen ? ' max-md:!hidden' : ''}`} style={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', borderRadius: '50%', border: 'none', background: 'var(--accent)',