feat(mobile): chat polish — floating composer + iOS keyboard handling + bottom-sheet drag-close + file-chip overflow
Multi-pass mobile chat polish landed across this session. - MessageInput is now a floating glass-bubble (`position: absolute`) on both desktop and mobile — last messages scroll *behind* the translucent bubble. MobileChatScreen wraps MessageList + MessageInput in a `relative` parent so absolute positioning resolves. Removed the prior in-flow mobile branch that clipped message-list bottom against an invisible barrier. - iOS PWA keyboard handling: new `useVisualViewportInset` hook subscribes to `visualViewport.resize/scroll` AND polls `vv.height` for ~600ms after focusin (iOS PWA standalone often fails to dispatch resize for keyboard transitions). MobileShell sizes its container to `vv.height` when keyboard is open — `bottom: 0` on the composer naturally lands flush with the keyboard top, regardless of how reliably resize events fire. Composer uses 6px gap above home indicator (keyboard closed) and 0px gap above keyboard (keyboard open). Added `interactive-widget=resizes-content` viewport meta as the cleaner native equivalent for Chrome/Android. - MessageList bottom padding is dynamic via `--composer-clearance` CSS variable. MessageInput writes `composerHeight + bottomOffset + 12px` to its parent via ResizeObserver — re-fires on textarea autosize, reply banner, attachment tile growth, parent resize. Last message always has 12px breathing room above the bubble regardless of composer state. - AttachmentRenderer generic file chip: `max-w-full sm:max-w-[400px]` on outer + `min-w-0` + `flex-shrink-0` on icon + `flex-1` on text + `flex-wrap` on badge row. Long filenames now ellipsize cleanly on narrow viewports instead of pushing the chip off-screen. - New `useDragToClose` hook: shared bottom-sheet drag-down-to-dismiss gesture. Spread on handle/header only (body scrolling unaffected). 6px deadzone, 100px or 0.5px/ms velocity threshold, 200ms `cubic-bezier(0.22, 1, 0.36, 1)` close-out animation, rAF-staged transform for a stable from-value. `hasInteracted` latch prevents the open keyframe from re-firing mid-close (the bounce-up-then-vanish bug). Wired into InputPopover (emoji/GIF), MobileVoiceJoinSheet, MobileFolderSheet. Specs: docs/systems/mobile-ui.md (Floating Composer + Drag-to-Close sections), docs/systems/message-list.md (--composer-clearance), docs/systems/design-system.md (glass-bubble row references).
This commit is contained in:
@@ -657,7 +657,11 @@ export function MessageList({ channelId, jumpToMessageId, onJumpComplete }: Mess
|
||||
|
||||
{!hasMore && <WelcomeHeader channelId={channelId} />}
|
||||
|
||||
<div ref={contentRef} className="pt-4 pb-6 md:pb-20">
|
||||
<div
|
||||
ref={contentRef}
|
||||
className="pt-4"
|
||||
style={{ paddingBottom: 'var(--composer-clearance, 80px)' }}
|
||||
>
|
||||
{interleavedMessages.map((msg, i) => {
|
||||
const prevMsg = interleavedMessages[i - 1];
|
||||
const showDate = shouldShowDateDivider(prevMsg, msg);
|
||||
|
||||
Reference in New Issue
Block a user