fix(mobile): make media gallery and members panel accessible on mobile
CI / Build & Quality Checks (push) Successful in 10m30s
CI / Trigger Desktop Build (push) Successful in 9s

MediaGallery: fixed panel now goes full-width (100%) on mobile instead
of the inaccessible 320px right sidebar. Added 'Media Gallery' MenuItem
to RoomMenu (visible only on mobile) so users can open it from the
More Options (···) button.

MembersDrawer: removed ScreenSize.Desktop gate in Room.tsx so it now
renders on mobile too. CSS media query (≤750px) makes it position:fixed
inset:0 width:100% on mobile instead of the 266px desktop sidebar.
Added 'Members' MenuItem to RoomMenu for mobile access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 18:21:58 -04:00
parent 8ac42cdbad
commit ffa490e767
4 changed files with 63 additions and 7 deletions
+5 -2
View File
@@ -21,6 +21,7 @@ import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { decryptFile, downloadEncryptedMedia, mxcUrlToHttp } from '../../utils/matrix';
import { ContainerColor } from '../../styles/ContainerColor.css';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
type GalleryTab = 'image' | 'video' | 'file';
@@ -531,6 +532,8 @@ type MediaGalleryProps = {
export function MediaGallery({ room, onClose }: MediaGalleryProps) {
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
const screenSize = useScreenSizeContext();
const isMobile = screenSize === ScreenSize.Mobile;
const [tab, setTab] = useState<GalleryTab>('image');
const [loading, setLoading] = useState(false);
@@ -650,9 +653,9 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
top: 0,
right: 0,
bottom: 0,
width: '320px',
width: isMobile ? '100%' : '320px',
zIndex: 500,
borderLeft: `1px solid ${color.Surface.ContainerLine}`,
borderLeft: isMobile ? 'none' : `1px solid ${color.Surface.ContainerLine}`,
overflow: 'hidden',
}}
>
@@ -3,6 +3,14 @@ import { config, toRem } from 'folds';
export const MembersDrawer = style({
width: toRem(266),
'@media': {
'(max-width: 750px)': {
position: 'fixed',
inset: 0,
width: '100%',
zIndex: 500,
},
},
});
export const MembersDrawerHeader = style({
+3 -1
View File
@@ -78,9 +78,11 @@ export function Room() {
<CallChatView />
</>
)}
{!callView && screenSize === ScreenSize.Desktop && isDrawer && (
{!callView && isDrawer && (
<>
{screenSize === ScreenSize.Desktop && (
<Line variant="Background" direction="Vertical" size="300" />
)}
<MembersDrawer key={room.roomId} room={room} members={members} />
</>
)}
+46 -3
View File
@@ -80,10 +80,14 @@ import { bookmarksPanelAtom } from '../../state/bookmarksPanel';
type RoomMenuProps = {
room: Room;
requestClose: () => void;
galleryOpen?: boolean;
onToggleGallery?: () => void;
};
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose }, ref) => {
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
({ room, requestClose, galleryOpen, onToggleGallery }, ref) => {
const mx = useMatrixClient();
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const screenSize = useScreenSizeContext();
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
const powerLevels = usePowerLevelsContext();
const creators = useRoomCreators(room);
@@ -99,6 +103,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
const [invitePrompt, setInvitePrompt] = useState(false);
const [reportRoomOpen, setReportRoomOpen] = useState(false);
const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
@@ -186,6 +191,38 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
Saved Messages
</Text>
</MenuItem>
{screenSize === ScreenSize.Mobile && (
<MenuItem
onClick={() => {
setPeopleDrawer(!peopleDrawer);
requestClose();
}}
size="300"
after={<Icon size="100" src={Icons.User} filled={peopleDrawer} />}
radii="300"
aria-pressed={peopleDrawer}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
Members
</Text>
</MenuItem>
)}
{screenSize === ScreenSize.Mobile && onToggleGallery && (
<MenuItem
onClick={() => {
onToggleGallery();
requestClose();
}}
size="300"
after={<Icon size="100" src={Icons.Photo} filled={galleryOpen} />}
radii="300"
aria-pressed={galleryOpen}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
Media Gallery
</Text>
</MenuItem>
)}
{!isServerNotice && (
<MenuItem
onClick={handleInvite}
@@ -288,7 +325,8 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
</Box>
</Menu>
);
});
},
);
type CallMenuProps = {
onVoiceCall: () => void;
@@ -783,7 +821,12 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) {
escapeDeactivates: stopPropagation,
}}
>
<RoomMenu room={room} requestClose={() => setMenuAnchor(undefined)} />
<RoomMenu
room={room}
requestClose={() => setMenuAnchor(undefined)}
galleryOpen={galleryOpen}
onToggleGallery={() => setGalleryOpen((v) => !v)}
/>
</FocusTrap>
}
/>