diff --git a/frontend/src/components/EmojiPicker.css b/frontend/src/components/EmojiPicker.css index c0f57d7..f60f9fe 100644 --- a/frontend/src/components/EmojiPicker.css +++ b/frontend/src/components/EmojiPicker.css @@ -88,3 +88,20 @@ .emoji-picker-item:hover { background: var(--ds-surface-2); } + +/* The picker is positioned absolutely relative to its trigger button, which + can sit close enough to a narrow viewport's edge that the full 320px + width runs off-screen (e.g. the composer's emoji trigger, near the left + edge, overflows the right edge on a 375px-wide phone). Shrinking the + fixed width -- rather than trying to dynamically reposition based on the + trigger's actual offset -- is enough margin for every real trigger + position in this app. */ +@media (max-width: 480px) { + .emoji-picker { + width: min(280px, calc(100vw - 32px)); + } + + .emoji-picker-grid { + grid-template-columns: repeat(7, 1fr); + } +} diff --git a/frontend/src/components/RoomInfoPanel.css b/frontend/src/components/RoomInfoPanel.css index e211f47..66d3854 100644 --- a/frontend/src/components/RoomInfoPanel.css +++ b/frontend/src/components/RoomInfoPanel.css @@ -28,6 +28,23 @@ background: color-mix(in srgb, var(--ds-accent) 40%, transparent); } +/* Below MOBILE_BREAKPOINT (frontend/src/hooks/useWindowWidth.ts), the + resizable-aside layout doesn't fit -- shown as a full-viewport overlay + instead. RoomInfoPanel.tsx skips its inline `style={{ width }}` on + mobile so this width rule isn't fighting an inline style, which would + otherwise win regardless of this media query's specificity. */ +@media (max-width: 859px) { + .room-info-panel { + position: fixed; + inset: 0; + z-index: 50; + width: 100%; + min-width: 0; + max-width: none; + border-left: none; + } +} + .room-info-header { display: flex; justify-content: space-between; diff --git a/frontend/src/components/RoomInfoPanel.tsx b/frontend/src/components/RoomInfoPanel.tsx index 0bb7b81..3ab423b 100644 --- a/frontend/src/components/RoomInfoPanel.tsx +++ b/frontend/src/components/RoomInfoPanel.tsx @@ -20,6 +20,7 @@ import { } from '../api/webhooks' import { useAuth } from '../context/AuthContext' import { useResizableWidth } from '../hooks/useResizableWidth' +import { MOBILE_BREAKPOINT, useWindowWidth } from '../hooks/useWindowWidth' import type { EventSubscription, EventType, @@ -57,6 +58,8 @@ export function RoomInfoPanel({ }: RoomInfoPanelProps) { const { user } = useAuth() const myRole = room.role + const windowWidth = useWindowWidth() + const isMobile = windowWidth < MOBILE_BREAKPOINT const { width, startResize } = useResizableWidth({ storageKey: 'room-info-panel-width', defaultWidth: 260, @@ -231,8 +234,8 @@ export function RoomInfoPanel({ } return ( -